描述

 15. 三数之和_技术

链接

 15. 三数之和 - 力扣(LeetCode) (leetcode-cn.com)

解法

去重的时候,注意:
left是逐渐增加的,应该与 过去的自己(比自己小一) 的作比较;
right是从length-1开始逐渐减小的,应该与 过去的自己(比自己大一) 的作比较。

 1 class Solution {
 2     public List<List<Integer>> threeSum(int[] nums) {
 3         List<List<Integer>> ans = new ArrayList<>();
 4         if (nums == null || nums.length <3) {
 5             return ans;
 6         }
 7         Arrays.sort(nums);
 8 
 9         for (int i = 0; i < nums.length -2; i++) {
10             if (nums[i] > 0 ) {
11                 break;
12             }
13             if (i > 0 && nums[i] == nums[i-1])  { //去重
14                 continue;
15             }
16             int target =  -nums[i];
17             int left = i + 1, right = nums.length - 1;
18             while (left < right) {
19                 if (nums[left] + nums[right] == target)  {
20                     ans.add(new ArrayList<>(Arrays.asList(nums[i],nums[left],nums[right])));
21 
22                     left++;
23                     right--;
24                     while (left < right && nums[left] == nums[left-1])  {   //去重
25                         left++;
26                     }
27                     while (left < right && nums[right] == nums[right+1])  { //去重
28                         right--;
29                     }
30                 }else if(nums[left] + nums[right] < target){
31                     left++;
32                 }else{
33                     right--;
34                 }
35             }
36         }
37         return ans;
38     }
39 }

 

// 下方的 去重过于 复杂,推荐上方的解法

 1 class Solution {
 2     public List<List<Integer>> threeSum(int[] nums) {
 3         List<List<Integer>> res = new ArrayList<>();
 4         Arrays.sort(nums);
 5 
 6         for (int i = 0; i < nums.length; i++) {
 7             if(nums[i] > 0) return res;
 8             if (i > 0 && nums[i] == nums[i-1]) continue; // 去重
 9 
10             int left = i+1, right = nums.length - 1;
11             while (left < right) {
12                 int sum = nums[i] + nums[left] + nums[right];
13                 if(sum < 0) {
14                     while( left < right && nums[left] == nums[++left]); //去重
15                 }
16                 else if(sum > 0) {
17                     while( left < right && nums[right] == nums[--right]); //去重
18                 }
19                 else{
20                     List<Integer> tmp = new ArrayList<>();
21                     tmp.add(nums[i]);
22                     tmp.add(nums[left]);
23                     tmp.add(nums[right]);
24                     res.add(tmp);
25                     //res.add(new ArrayList<Integer>(Arrays.asList(nums[i], nums[left], nums[right])));
26                     while( left < right && nums[left] == nums[++left]); //去重
27                     while( left < right && nums[right] == nums[--right]); //去重
28                 }
29             }
30         }
31         return res;
32     }
33 }

15. 三数之和_i++_02

 

有个问题

容易混淆的解法
正确解法,但下述的 去重比较复杂,且容易把 去重
nums[left] == nums[++left]);
nums[right] == nums[--right]);
误写为
nums[left] == nums[left++]); // 注意 left++ 与 ++left的区别
nums[right] == nums[right--]);
或者误写为
nums[--right] == nums[right]);
都得不到完整的答案。

------------------------

添加结果少一个,在于 nums[right--] == nums[right]; 以及 nums[--right] == nums[right]; 是不对的。

需要仔细思考 nums[right] == nums[--right]  和 nums[left] == nums[++left] 的边界条件,比较复杂!

 1 class Solution {
 2     public List<List<Integer>> threeSum(int[] nums) {
 3         List<List<Integer>> res = new ArrayList<>();
 4         Arrays.sort(nums);
 5         
 6         for (int i = 0; i < nums.length; i++) {
 7             if(nums[i] > 0) return res;
 8             if (i > 0 && nums[i] == nums[i-1]) continue; // 去重
 9 
10             int left = i+1, right = nums.length - 1;
11             while (left < right) {
12                 int sum = nums[i] + nums[left] + nums[right];
13                 if(sum < 0) {
14                     while( left < right && nums[left] == nums[left++]); //去重
15                 }
16                 else if(sum > 0) {
17                     while( left < right && nums[right--] == nums[right]); //去重
18                 }
19                 else{
20                     List<Integer> tmp = new ArrayList<>();
21                     tmp.add(nums[i]);
22                     tmp.add(nums[left]);
23                     tmp.add(nums[right]);
24                     // res.add(tmp);
25                     res.add(new ArrayList<>(tmp));
26                     while( left < right && nums[left] == nums[left++]); //去重
27                     while( left < right && nums[right--] == nums[right]); //去重
28                 }
29             }
30         }
31         return res;
32     }
33 }

结果

15. 三数之和_边界条件_03

 

 

题解链接

 三数之和(排序+双指针,易懂图解) - 三数之和 - 力扣(LeetCode) (leetcode-cn.com)