携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第5天,点击查看活动详情
她的客气, 让我觉得很生疏很有距离感,让我觉得 ,我多努力都走不到她的身边 。我很清楚我根本没有能让她喜欢的本事, 所以我一直在鼓励自己, 把自己的价值提一提。可能最终无济于事, 但也至少不会让她反感
原题链接:15-三数之和
给你一个包含 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 = [0,1,1]
输出: []
示例 3:
输入: nums = [0,0,0]
输出: [[0,0,0]]
提示:
3 <= nums.length <= 3000-10^5 <= nums[i] <= 10^5
思路
- 先对数组进行排序,保证首项最小,尾项最大
- 再对数组进行遍历,使用左右指针指向
nums[i]的两端,然后计算三个数的和判断是否为0,满足则添加进返回数组中 - 接下来如何移动左右指针呢, 如果
nums[i] + 左指针 + 右指针 > 0就说明 此时三数之和大了,因为数组是排序后了,所以右指针的下标就应该向左移动,这样才能让三数之和小一些。如果nums[i] + 左指针 + 右指针 < 0说明 此时 三数之和小了,左指针 就向右移动,才能让三数之和大一些,直到左右指针相遇为止中断循环 - 对i、左右指针做去重处理,避免结果重复
Code
const threeSum = nums => {
const len = nums.length
const res = []
// 双指针法必须排序
nums.sort((a, b) => a - b)
if (nums[0] <= 0 && nums[len - 1] >= 0) {
for (let i = 0; i < len - 2;) {
let left = i + 1, right = len - 1;
do {
if (left >= right || nums[i] * nums[right] > 0) break;
let sum = nums[i] + nums[left] + nums[right]
if (sum === 0) {
res.push([nums[i], nums[left], nums[right]])
}
if (sum <= 0) {
while (left < right && nums[left] === nums[++left]); //左指针去重 一直找到不相同的那个坐标
}
else {
while (left < right && nums[right] === nums[--right]); //右指针去重 一直找到不相同的那个坐标
}
}
while (left < right);
while(nums[i]===nums[++i]); // 对i的去重 若当前这一项和下一项相等则跳过
}
}
return res
}
复杂度分析
- 时间复杂度:
O(n^2) - 空间复杂度:
O(1)