文章目录
- 前言
- 一、三数之和
- 1, 题目
- 2, 思路分析
- 3, 代码
前言
各位读者好, 我是小陈, 这是我的个人主页, 希望我的专栏能够帮助到你:
📕 JavaSE基础: 基础语法, 类和对象, 封装继承多态, 接口, 综合小练习图书管理系统等
📗 Java数据结构: 顺序表, 链表, 堆, 二叉树, 二叉搜索树, 哈希表等
📘 JavaEE初阶: 多线程, 网络编程, TCP/IP协议, HTTP协议, Tomcat, Servlet, Linux, JVM等(正在持续更新)
一、三数之和
1, 题目
OJ链接
这题是在"两数之和"的基础上进行了一些提升, 核心算法思想是一致的, 不熟悉 “两数之和” 这道题的小伙伴建议看一下 这道题的分析 会对本题的理解有很大帮助
2, 思路分析
最简单的暴力枚举 : 三层 for 循环, 从先固定一个数, 在剩余区间上固定一个数, 暴力枚举依次找第三个数, 判断这三个数的和是否为 0 (目标值), 时间复杂度为O(N³), 必然会超出时间限制
我们已经有了 两数之和 这道题的基础, 那完全可以 :
- 先对数组排序(有序后使用对撞双指针可以大大提高效率)
- 使用 i 指针先固定一个数
- 在剩余区间上使用 “两数之和” 的解法找到另外两个数
注意, 这个 target 的值, 在本题中应该是 0 - i 下标的值
还需要注意, 题中要求找到不重复的三个数, 所以需要进行去重操作
- 当 left 和 right 指针找到符合条件的两个数后, left++, right–, 但还需要 left 判断当前 left 是否等于下一个 left , right 判断当前 right 是否等于下一个 right, 如果等于, 要对 left / right 去重
- 当 i++ 之后需要判断当前这个 i 是否和刚才的值相等, 如果相等, 要对 i 去重
- 初始位置 i 指向 0 下标
-
i 指向 0 下标时, 使用双指针遍历完了剩余区间, 让 i++
-
i 指向 1 下标时, 使用双指针遍历完了剩余区间, 让 i++, 此时 i 到了 2 下标, 和 i 在 1 下标时的值相等, i 继续自增(去重)
后续步骤省略
3, 代码
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> list = new ArrayList<>();
Arrays.sort(nums);
int i = 0;
while(i < nums.length - 2) {
if(nums[i] > 0) {
return list;
}
int target = 0 - nums[i];
int left = i + 1;
int right = nums.length - 1;
while(left < right) {
List<Integer> inList = new ArrayList<>();
if(nums[left] + nums[right] > target) {
right--;
}else if(nums[left] + nums[right] < target) {
left++;
}else {
while(left < right && nums[right] == nums[right - 1]) {
right--;
}
while(left < right && nums[left] == nums[left + 1]){
left++;
}
inList.add(nums[i]);
inList.add(nums[left]);
inList.add(nums[right]);
list.add(inList);
left++;
right--;
}
}
i++;
while(nums[i] == nums[i - 1] && i < nums.length - 2) {
i++;
}
}
return list;
}