题目
题目地址:https://leetcode.cn/problems/3sum/
示例
方法1:排序+双指针
思路参考了作者:Krahets
https://leetcode.cn/problems/3sum/solution/3sumpai-xu-shuang-zhi-zhen-yi-dong-by-jyd/
我的思路:
先排序数组
定义三个指针:最左(leftMost)、左(left)、右(right)
最左指针放在数组的最左边,左、右指针放在 最左指针的右边 的左右两段。
如果nums[leftMost]>0,那别找了,没戏了,最左都>0,后面的肯定也>0,不能能三指针相加=0。直接返回结果。
左、右指针一个一个的往中间走:
当三者相加<0时,left++,并跳过重复的元素
当三者相加=0时,记录下结果,lefrt和right同时移动:left++ ;right--;并跳过重复的元素
当三者相加>0时,right--,并跳过重复的元素
当left 不小于 right 时,说明这一轮都找完了,开始将leftMost向右移动,并跳过重复元素,注意,leftMost指的数据一定要<0
举例说明
当left 不小于 right ,说明leftMost在当前的情况全部找完了,开始将leftMost右移动,进行新一轮的寻找
这一轮也结束了,leftMost++,并跳过重复
我写的代码虽然丑,但它宝贵在它是我亲手写的。即使有了思路,代码也不是一下子就能写出来,例如很多的边界条件设置、防止数组越界之类的问题,所以建议照着思路先自己写出一个通过的代码,再去参考别人的代码。
我的代码:
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> result = new ArrayList<List<Integer>>();
//先排序
Arrays.sort(nums);
int leftMost = 0;
while(leftMost<nums.length-2 && nums[leftMost]<=0){
int left = leftMost+1;
int right = nums.length-1;
while (left<right && left<nums.length-1 && right>0){
int sum = nums[leftMost]+nums[left]+nums[right];
if (sum == 0){
//将正确结果添加上
List<Integer> arr = new ArrayList<Integer>();
arr.add(nums[leftMost]);
arr.add(nums[left]);
arr.add(nums[right]);
result.add(arr);
//left右移 去重
if (left<=nums.length-2){
while ( left<=nums.length-2 && nums[left] == nums[left+1]){
left++;
}
left++;
}else break;;
//right左移 去重
if (right>=2){
while ( right>=2 && nums[right] == nums[right-1]){
right--;
}
right--;
}else break;
}else if (sum < 0){
//left右移 去重
if (left<=nums.length-2){
while ( left<=nums.length-2 && nums[left] == nums[left+1]){
left++;
}
left++;
}else break;;
}else {
//right左移 去重
if (right>=2){
while ( right>=2 && nums[right] == nums[right-1]){
right--;
}
right--;
}else break;
}
}
//leftMost右移 去重
if (leftMost<nums.length-3){
while (leftMost<nums.length-3 && nums[leftMost] == nums[leftMost+1]){
leftMost++;
}
leftMost++;
}else break;
}
return result;
}
}
效果
思路有了,写代码也是花费了很多时间,还是得多练
别人(Krahets)优秀的代码
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
Arrays.sort(nums);
List<List<Integer>> res = new ArrayList<>();
for(int k = 0; k < nums.length - 2; k++){
if(nums[k] > 0) break;
if(k > 0 && nums[k] == nums[k - 1]) continue;
int i = k + 1, j = nums.length - 1;
while(i < j){
int sum = nums[k] + nums[i] + nums[j];
if(sum < 0){
while(i < j && nums[i] == nums[++i]);
} else if (sum > 0) {
while(i < j && nums[j] == nums[--j]);
} else {
res.add(new ArrayList<Integer>(Arrays.asList(nums[k], nums[i], nums[j])));
while(i < j && nums[i] == nums[++i]);
while(i < j && nums[j] == nums[--j]);
}
}
}
return res;
}
}
效果
我的代码和他的代码思路一样,执行用时也就差不多