class Solution { public List<List<Integer>> threeSum(int[] nums) { Arrays.sort(nums); List<List<Integer>> res = new ArrayList(); for(int i = 0; i < nums.length - 2; i++){ if(i > 0 && nums[i] == nums[i-1]) continue; if(nums[i] > 0) return res; int lo = i+1, hi = nums.length - 1, sum = -nums[i]; while(lo < hi){ int cur = nums[lo] + nums[hi]; if(cur == sum) { res.add(Arrays.asList(nums[i], nums[lo], nums[hi])); while(lo < hi && nums[lo+1] == nums[lo]) lo++; while(lo < hi && nums[hi-1] == nums[hi]) hi--; lo++; hi--; } else if(cur < sum) lo++; else hi--; } } return res; } }
我看这个解答,一开始反复卡在左边界lo为什么==i+1,说是为了避免重复。
后来举例子【-4,-3,1,7】,-4能和-3和7成对,到了-3,如果从0开始,就会也形成-4,-3和7,这样就重复了。所以每次左边界都要从i+1开始
或者这样理解,i是可能解的左下标,lo是中间,hi是右边,所以lo = i + 1
3sum就是固定一个数,剩下就是一个2sum,但题目要求不能有重复triplets出现,所以需要去重
具体方法是先对数组排序,i代表合适解的左下表,所以是i < nums.length - 2, 从下标1开始如果和前面重复就continue,然后如果nums[ i ] > 0就break,因为后面数都比他大不可能还有解。
然后就是具体情况,lo和hi和target设置好,如果lo+hi == target就是一个解,然后左右向中间靠拢,这里也要考虑重复元素,排除重复后更新lo和hi
最后返回即可。