题目
给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/3sum
思路
先对数组进行排序
以i
为数组首,j
为数组尾,在i
与j
直接寻找k能使得nums[i] + nums[j] + nums[k] == 0
。当k
从i
走到j
时,说明中间已经遍历完了,然后令i
右移一位,j
重新回到数组尾部,继续寻找k
。
去重
- nums[i] != nums[i - 1]
if (i > 0 && nums[i] == nums[i - 1])
continue;
注意,是nums[i] != nums[i - 1]
,不是nums[i] != nums[i + 1]
,如果是nums[i] == nums[i - 1],在上一个循环中就已经取到了所有情况;如果是nums[i] == nums[i + 1]就跳出,那么nums[i]和nums[k]就不能取到相同的值。
同样注意
if (i > 0 && nums[i] == nums[i - 1])
continue;
与
while (i > 0 && nums[i] == nums[i - 1])
i++;
不同,前者进行一次for循环的界限判断。
- k递增
每当有nums[i] + nums[j] + nums[k] == 0
成立,k就要往右移一位。要保证k不能移动到相同的值,如数组[0,0,0,0],k初始为1,得到一个结果[0,0,0],k右移一位,nums[k]还是为0,又得到一个结果[0,0,0]。所以k移动过程中,nums[k] != nums[k-1]
。代码如下:
do {
k++;
}while (k < j && nums[k] == nums[k-1]);
完整代码
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> result = new ArrayList<List<Integer>>();
if ( nums.length <3)
return result;
Arrays.sort(nums);
for (int i = 0; i < nums.length; i++) {
if(nums[i] > 0)
return result;
if (i > 0 && nums[i] == nums[i - 1])
continue;
int j = nums.length-1;
int k = i+1;
while (k < j)
{
if (nums[i] + nums[j] + nums[k] == 0)
{
List<Integer> result1 = new ArrayList<Integer>();
result1.add(nums[i]);
result1.add(nums[k]);
result1.add(nums[j]);
result.add(result1);
do {
k++;
}while (k < j && nums[k] == nums[k-1]);
}
else if (nums[i] + nums[j] + nums[k] < 0) {
k++;
} else {
j--;
}
}
}
return result;
}
}