题目
题目链接
描述
给出一个有n个元素的数组S,S中是否有元素a,b,c满足a+b+c=0?找出数组S中所有满足条件的三元组。
注意:
三元组(a、b、c)中的元素必须按非降序排列。(即a≤b≤c)
解集中不能包含重复的三元组。
例如,给定的数组 S = {-10 0 10 20 -10 -40},解集为(-10, -10, 20),(-10, 0, 10)
分析
直接找三个数之和等于0比较麻烦,直接找替代方案,b+c = -a;
由于结果中的数据需要有序,所以我们需要先将数组排序,然后循环,将每个数字作为target时,看看能否找到匹配的,由于有序,我们就可以用滑动窗口来实现匹配搜索。
如果a[left] + a[right] > target; 那么说明right需要向左移动;反之,left向右移动。
还需要注意的点是需要去重,由于已经排序了,所以相等的值肯定是相邻的,
大循环时对于相等的值直接跳过,不重复做target;小循环中匹配时也需要去重。
代码实现
import java.util.*;
public class Solution {
public ArrayList<ArrayList<Integer>> threeSum(int[] num) {
ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>();
if (num.length < 3) return res;
Arrays.sort(num);
int n = num.length;
for (int i = 0; i < n - 2; i++) {
if (i != 0 && num[i] == num[i - 1]) continue; //避免重复
int left = i + 1;
int right = n - 1;
int target = -num[i];
while (left < right) {
if (num[left] + num[right] == target) {
ArrayList<Integer> temp = new ArrayList<>();
temp.add(num[i]);
temp.add(num[left]);
temp.add(num[right]);
res.add(temp);
//由于数组已经有序,所以相等的必然相邻
while (left + 1 < right && num[left] == num[left + 1])
left ++;
while (right - 1 > left && num[right] == num[right - 1])
right --;
left ++;
right --;
} else if (num[left] + num[right] < target) {
left ++;
} else {
right --;
}
}
}
return res;
}
}