题意:
给出一个数组,在其中找到三个数,之和为0,输出所有的解。
例子:输入S = [-1, 0, 1, 2, -1, -4],
输出[
[-1, 0, 1],
[-1, -1, 2]
]
错误尝试一:
三层循环- –超时
正确做法:确定一个数,再用双指针法找剩余两个数
beadt 91%
- 数组由小到大排序
- 遍历每一个数num,若num不等于他之前的数(等于那么无需判断,已经判断过),那么,在他之后的子数组找到两个数,使之和为num的相反数opp
如何找他之后的两个数?
- 两个指针,一个指向子数组头,一个指向尾,
- 如果和大于opp,那么high–,
- 如果和小于opp,那么low++
- 如果和==opp,那么加入res,并且!!!判断下一个数是否相等nums[low] nums[high,如果相等,无需进行计算直接low++ 或者high–
- 直到两指针相遇
Tips:
- 将多个整数生成一个list:
Arrays.asList(num[i], num[lo], num[hi])
- 如果成功找到组合并且nums[low] == nums[low + 1]或者nums[high] == nums[high - 1],即有重复组合,那么直接low++ 或者high–,直至该数字无重复。
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
Arrays.sort(nums);
int len = nums.length;
if (len < 3 || nums[0] > 0 || nums[len - 1] < 0) {// skip same result
return res;
}
for(int i = 0; i < len - 2; i++){
if (i > 0 && nums[i] != nums[i - 1]) {
continue;
}
int low = i + 1;
int high = len - 1;
int opp = 0 - nums[i];
while (low < high) {
int sum = nums[low] + nums[high];
if (sum < opp) low++;
else if(sum > opp) high--;
else {
res.add(Arrays.asList(nums[i], nums[low], nums[high]));
while(low < high && nums[low] == nums[low + 1])// skip same result low++;
while(low < high && nums[high] == nums[high - 1])// skip same result high--;
low++;
high--;
}
}
}
return res;
}