三数之和
一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第8天,点击查看活动详情。
算题
给你一个包含 n
个整数的数组 nums
,判断 nums
中是否存在三个元素,a,b,c , 使得 a + b + c = 0 ?请你找出所有和为 0
且不重复的三元组。
注意: 答案中不可以包含重复的三元组。
示例 1:
输入: nums = [-1,0,1,2,-1,-4]
输出: [[-1,-1,2],[-1,0,1]]
示例 2:
输入: nums = []
输出: []
示例 3:
输入: nums = [0]
输出: []
提示:
0 <= nums.length <= 3000
-105 <= nums[i] <= 105
解析
言简意赅,完成这个需求就必须实现:
1. 三数之和等于0
2.不可出现重复的数字组合(可出现重复的数字)
先看第二个需求:不重复,这就表示我们不能出现三个同样的数字组成的数组,为了避免这种情况,最简单的实现就是排序,排序之后相同的数字必然是相邻的,那么在遍历的时候判断跳过即可。三数之和等于0,可以在遍历的同时使用双指针,每一次遍历循环使用双指针去相加:(以从小到大排序为例)
1. 相加等于0,那么结果 + 1
2. 相加大于0,那么右置针左移
3. 相加小于0,那么左指针右移
代码实现:
var threeSum = function (nums) {
let result = []; // 结果数组
let arr = nums.sort((a, b) => a - b); // 排序
for (let i = 0; i < arr.length; i++) { // 循环遍历数组
if (arr[i] > 0) break; // 如果当前数字大于0,则跳出循环
if (i > 0 && arr[i] === arr[i - 1]) continue; // 如果当前数字与上一个数字相同,则跳过,避免重复
let left = i + 1; // 左指针
let right = arr.length - 1; // 右指针
while (left < right) { // 左右指针循环
let sum = arr[i] + arr[left] + arr[right]; // 当前数字与左右指针的和
if (sum === 0) { // 如果和为0
result.push([arr[i], arr[left], arr[right]]); // 将结果添加到结果数组
while (left < right && arr[left] === arr[left + 1]) left++; // 如果左指针与左指针+1相等,则左指针+1
while (left < right && arr[right] === arr[right - 1]) right--; // 如果右指针与右指针-1相等,则右指针-1
left++; // 左指针+1
right--; // 右指针-1
} else if (sum > 0) { // 如果和大于0
right--; // 右指针-1
} else {
left++; // 左指针+1
}
}
}
return result;
};
附上提交结果: