给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例:
给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]
思路:先进行整体排序,从第一个开始,固定一个数,通过sum判断左移还是右移,具体解析可以参考guanpengchn的答案解析
解题:
var threeSum = function (nums) {
let ans = []
let len = nums.length
if (nums == null || len < 3) return ans
nums.sort((a, b) => a - b) //从小到大排序
for (let i = 0; i < len; i++) {
if (nums[i] > 0) {
break //停止
}
// 排除重复的部分
if (i > 0 && nums[i] == nums[i - 1]) {
continue //跳过
}
let left = i + 1,
right = len - 1
// 排除重复的部分
while (left < right) {
sum = nums[left] + nums[right] + nums[i]
if (sum == 0) {
ans.push([nums[left], nums[right], nums[i]])
while (left < right && nums[left] == nums[left + 1]) left++
while (left < right && nums[right] == nums[right - 1]) right--
left++
right--
} else if (sum < 0) left++
else if (sum > 0) right--
}
}
return ans
}
但是需要注意点:
-
以下两句代码必须这么写,
left<right
保证了不因 触发最外层while循环条件而导致后续不执行,例如
[-2,0,1,1,2],由于1等于1若没有条件限制,很容易走向left++使得left>=right退出循环,而导致缺少[-2,1,1]这个答案 -
而
nums[left] == nums[left + 1]
也是必须的,写错为nums[left] == nums[left -1]
明显不对,若第一次取值就与前面的相同,那取到的是nums[i]的值,不是nums[left]的值,例如[-4,-1,-1,0,1,2],当i=-1时,nums[left] == nums[left - 1] 为-1,推进数组之后,连续两次left++,此时0还没进行计算就跳到下一个,忽略了[-1,0,1]这个答案 -
必须写在
sum==0
条件内,因为只有相等,才需要处理去重,否则例子[-2,0,1,1,2],一次相等后,指针同时向内的时候得到一个sum==0
,但是由于去重处理,导致直接退出了循环,导致缺少[-2,1,1]这个答案。
while (left < right && nums[left] == nums[left + 1]) left++
while (left < right && nums[right] == nums[right - 1]) right--
答案参考自:
作者:guanpengchn
链接:https://leetcode-cn.com/problems/3sum/solution/hua-jie-suan-fa-15-san-shu-zhi-he-by-guanpengchn/