java数据结构与算法刷题-----LeetCode15. 三数之和

java数据结构与算法刷题目录(剑指Offer、LeetCode、ACM)-----主目录-----持续更新(进不去说明我没写完):https://blog.csdn.net/grd_java/article/details/123063846

在这里插入图片描述

解题思路
  1. 和LeetCode1.两数之和一样,但是这道题边界条件更多。
  2. 两数之和那道题目中,我们使用了map进行处理,也讲了如果投机取巧,用大量的数组空间充当map集合,从而达成相同的逻辑处理代码,只是将map换成数组,却比map集合快很多的办法。
  3. 这道题也同样可以用map集合,但是因为边界条件过多,代码十分繁琐,尤其是投机取巧用数组充当hash,确实在做题方面,可以达成超越100%的用户,但是没有任何实际意义,只能做题。(后面也会将代码给出)
  4. 所以这道题,我会给出比较靠谱的办法,时间复杂度也不高,工作中推荐使用。那就是排序+双指针
  5. 先对整个数组排序,然后创建3个指针,从第一个数开始向后枚举
  6. 第一个指针 i 只是起到限定第一个数的作用,我们需要通过双指针left和right,来找到第一个数的右边区域的另外两个数
  7. 初始left左指针指向第一个数 i 的右边第一个位置,而right指向右边区域末尾,如果3个数相加比0大,就说明right指向的数太大,right–即可,反之,如果相加比0小,left就太小了,进行left++。
代码,时间复杂度O(n^2),空间复杂度,数组需要排序,工作场景中,不可以改变原数组,因此需要O(n)空间复杂度来排序。然后排序算法使用快速排序,需要O(logN)的栈空间复杂度。
  1. 方法一:排序+双指针,效率肯定比不过方法二的hash表,而且使用数组当hash表,但是实际工作中,肯定使用方法一。此方法耗时25ms, 方法二耗时0ms
    在这里插入图片描述
class Solution {public List<List<Integer>> threeSum(int[] nums) {Arrays.sort(nums);//先排序,为了双指针枚举提供方便List<List<Integer>> ans = new ArrayList<>();//答案需要的链表int n = nums.length;//n代表数组长度for (int i = 0; i < n - 2; ++i) {//因为需要3个数,所以第一个数最多到---倒数第3个int x = nums[i];//x保存当前遍历的第一个数if (i > 0 && x == nums[i - 1]) continue; // 跳过重复数字,枚举过的,就不重复枚举了// 优化一:因为数组排序后是从小到大,如果当前第一个数+它后面两个数,就已经>0了,那当前枚举,包括后面的,都不会符合条件if (x + nums[i + 1] + nums[i + 2] > 0) break; // 优化二:如果当前数+倒数那两个数(从小到大排序,也就是末尾的都是最大的)都小于0的话,那也就不用在考虑这个枚举了。肯定枚举不出来if (x + nums[n - 2] + nums[n - 1] < 0) continue; //左右指针int left = i + 1, right = n - 1;while (left < right) {//只要还有元素可以枚举就继续int s = x + nums[left] + nums[right];//3个数的和if (s > 0) --right;//如果s比0大,说明right指向的太大的,right--else if (s < 0) ++left;//如果s比0小,说明left指向太小,left++else {//如果s = 0,说明找到了,添加到链表,然后将继续进行下次枚举ans.add(List.of(x, nums[left], nums[right]));//添加到链表//进行下次枚举之前,我们可以跳过已经枚举过的,也就是和当前left和right数字重复的//因为答案中不要重复的元素for (++left; left < right && nums[left] == nums[left - 1]; ++left); // 跳过重复数字for (--right; right > left && nums[right] == nums[right + 1]; --right); // 跳过重复数字}}}return ans;//返回答案}
}
  1. 方法二:使用hash表,用数组充当hash,空间复杂度不确定,取决于数组中存储的值的范围,如果一共有两个元素,[1,999999],那么空间复杂度就是999999. 所以,这是投机取巧的方法,但是做题的效率确实快。只用了0ms
    在这里插入图片描述
//C(n, k) = C(n - 1, k) + C(n - 1, k - 1)
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;class Solution {public List<List<Integer>> threeSum(int[] nums) {return nSum(nums, 3, 0);}public List<List<Integer>> fourSum(int[] nums, int target) {return nSum(nums, 4, target);}public List<List<Integer>> nSum(int[] nums, int k, int target) {return new AbstractList<List<Integer>>() {final List<List<Integer>> res = new ArrayList<>();final List<Integer> path = new ArrayList<>();long min;@Overridepublic List<Integer> get(int index) {init();return res.get(index);}@Overridepublic int size() {init();return res.size();}public void init() {if (res.isEmpty()) {int n = nums.length;long[] Arr = new long[n];Arrays.sort(nums);min = nums[0];for (int i = 0; i < n; i++) {Arr[i] = nums[i] - min;}long NewTarget = (long)target - (long)k * min;C(false, Arr, n, k, NewTarget);}}//C(n, k) = C(n - 1, k) + C(n - 1, k - 1)public void C(boolean T, long[] a, int n, int k, long target) {if (n == 0 || k == 0) {if (target == 0 && k == 0) {res.add(new ArrayList<>(path));}return;}if (k == 2) {if (!T && n != a.length && a[n] == a[n - 1]) {return;}//两数之和模板twoSum(a, 0, n - 1, target);return;}if (n == k) {if (!T && n != a.length && a[n] == a[n - 1]) {return;}//数组中元素和是否等于targetsumArr(a, n, target);return;}if (check(a, n, k, target)) {return;}C(false, a, n - 1, k, target);if (!T && n != a.length && a[n] == a[n - 1]) {return;}if (target - a[n - 1] >= 0) {path.add((int) (a[n - 1] + min));C(true, a, n - 1, k - 1, target - a[n - 1]);path.remove(path.size() - 1);}}void twoSum(long[] a, int l, int r, long target) {if (l >= r || a[r - 1] + a[r] < target || a[l] + a[l + 1] > target) {return;}while (r > l) {long sum = a[l] + a[r];if (sum < target) {l++;} else if (sum > target) {r--;} else {path.add((int) (a[l] + min));path.add((int) (a[r] + min));res.add(new ArrayList<>(path));path.remove(path.size() - 1);path.remove(path.size() - 1);while (r > l && a[l] == a[l + 1]) {l++;}while (r > l && a[r] == a[r - 1]) {r--;}l++;r--;}}}void sumArr(long[] a, int n, long target) {for (int i = n - 1; i > -1; i--) {target -= a[i];path.add((int) (a[i] + min));}if (target == 0) {res.add(new ArrayList<>(path));}for (int i = n - 1; i > -1; i--) {target += a[i];path.remove(path.size() - 1);}}boolean check(long[] a, int n, int k, long target) {if (n - k < 0) {return true;}long max = 0;long min = 0;for (int i = 0; i < k; i++) {min += a[i];max += a[n - i - 1];}if (target < min || target > max) {return true;}return false;}};}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/450069.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2021-10-18 51蛋骗鸡数码管显示0-F每6个切换循环

缘由我的单片机流水灯程序不知道为什么无法很好的显示? - 24小时必答区 #include "REG52.h" sbit K1 P3^0; sbit K2 P3^1; sbit K3 P3^2; sbit K4 P3^3; sbit bpP3^4; bit k1,wk0; unsigned char code SmZiFu[]{63,6,91,79,102,109,125,7,127,111,119,124,57,94…

LabVIEW汽车自燃监测预警系统

LabVIEW汽车自燃监测预警系统 随着汽车行业的飞速发展&#xff0c;汽车安全问题日益受到公众的关注。其中&#xff0c;汽车自燃现象因其突发性和破坏性&#xff0c;成为一个不可忽视的安全隐患。为了有效预防和减少自燃事故的发生&#xff0c;提出了LabVIEW的汽车自燃监测预警…

【Java程序设计】【C00240】基于Springboot的班级综合测评管理系统(有论文)

基于Springboot的班级综合测评管理系统&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的班级综合测评管理系统 本系统分为学生功能模块、管理员功能模块以及教师功能模块。 管理员功能模块&#xff1a;管理员功能…

Leetcode高频题:198打家劫舍1

题目链接力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 题目描述 你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋。每间房内都藏有一定的现金&#xff0c;影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统&#xff0c;如果两间相…

Jetpack Compose系列(3)-使用列表

使用列表 在 View 体系中&#xff0c;创建自定义布局必须扩展 ViewGroup 并实现测量和布局函数。在 Compose 中&#xff0c;只需使用 Layout 可组合项编写一个(布局)函数即可。上一篇文章我们详细介绍了Column()和Row()这两各横向布局&#xff0c;这里我们继续介绍其他布局。 …

C++输出地址

下面是一段输出地址的程序。 #include <bits/stdc.h> using namespace std;int main() {int s;cout << &s;//原地址return 0; }假如有一个人&#xff08;的朋友&#xff09;后来了&#xff0c;他也想住进的房间&#xff0c;我们可以这样&#xff1a; #includ…

Python爬虫http基本原理

Python爬虫逆向系列&#xff08;更新中&#xff09;&#xff1a;http://t.csdnimg.cn/5gvI3 HTTP 基本原理 在本节中&#xff0c;我们会详细了解 HTTP 的基本原理&#xff0c;了解在浏览器中敲入 URL 到获取网页内容之间发生了什么。了解了这些内容&#xff0c;有助于我们进一…

阿里云智能集团副总裁安筱鹏:企业数字化的终局是什么?

以下文章来源于数字化企业 &#xff0c;作者安筱鹏博士 回答数字化终局追问的起点是&#xff0c;企业需要重新定义我是谁。成为有竞争力的行业领导厂商&#xff0c;你应当成为一个客户运营商&#xff0c;即能够实时洞察、实时满足客户需求&#xff0c;追求极致的客户体验。而要…

SPI指数计算(Standardized Precipitation Index,标准化降水指数) 附完整MATLAB代码

SPI指数(Standardized Precipitation Index,标准化降水指数)是反映干湿状况的一个指标,主要计算步骤如下: 收集研究区域过去30年或以上时间尺度(一般选取30年)的月降水量资料。 对月降水量资料进行统计分析,拟合出最适合的概率分布函数。常用的有Pearson III 分布、Gamma分布…

2024年美国大学生数学建模竞赛(美赛)C题代码

代码只写了核心部分、包括数据预处理和建模等&#xff0c;仅供参考 获取方法见文末&#xff0c;部分截图如下 免费获取代码 关注威信公众号 Python风控模型与数据分析&#xff0c;回复 24年美赛C题代码 文末查看如何免费获取代码&#xff1b;编写不易&#xff0c;辛苦多多关注…

【C++】类与对象(三)—运算符重载|const成员函数|取地址及const取地址操作符重载

前言 运算符重载&#xff0c;自增自减运算符重载&#xff0c;const成员函数&#xff0c;取地址及const取地址操作符重载 文章目录 一、运算符重载自增和自减运算符重载 二、const 成员函数三、取地址及const取地址操作符重载&#xff08;了解即可&#xff09; 一、运算符重载 运…

【微服务】skywalking自定义链路追踪与日志采集

目录 一、前言 二、自定义链路追踪简介 2.1 自定义链路追踪应用场景 2.2 链路追踪几个关键概念 三、skywalking 自定义链路追踪实现 3.1 环境准备 3.2 集成过程 3.2.1 导入核心依赖 3.2.2 几个常用注解 3.2.3 方法集成 3.2.4 上报追踪信息 四、skywalking 自定义日志…