【题目】15. 三数之和
【题目考察】:双指针
【目标复杂度】: O(n^2)
【解法】:
/**
* @param {number[]} nums
* @return {number[][]}
*/
var threeSum = function(nums) {
// 定义res存储结果数组
const res = [];
// 升序排序
nums.sort((a, b) => a - b);
if (
// 空
!nums ||
// 数组长度小于3
nums.length < 3 ||
// 升序排序后第一个数字大于0
nums[0] > 0
) {
// 直接返回空数组
return res;
}
// nums从第一个数字遍历,接着第二第三个从后面取
for (let i = 0; i < nums.length; i++) {
// nums是升序排序过的,如果第一个数字都为0,比如0, 0, 1, 肯定和大于0,直接不断continue结束就好了
if (nums[i] > 0) {
continue;
}
// 比如-1,-1,0,1,其实两个-1是重复的,跳过重复的去重
if (nums[i] === nums[i - 1]) {
continue;
}
// 定义左边指针
let left = i + 1;
// 定义右指针
let right = nums.length - 1;
// 进行while循环判断left和right 条件是left 小于 right 由两边向中间夹,left肯定是比right小的,相等或者大了的就结束
while (left < right) {
// 取三个数之和
const sum = nums[i] + nums[left] + nums[right];
if (sum === 0) {
// 如果等于0,那么就把对应的数字放到结果数组中
res.push([nums[i], nums[left], nums[right]]);
// 接着对左边去重
while(nums[left] === nums[left + 1]) {
left++;
}
// 对右边去重
while(nums[right] === nums[right - 1]) {
right--;
}
// 去重后其实上面哪个数字还是之前那个一样的,所以需要左边右边都移动一位
left++;
right--;
} else if (sum > 0) {
// 如果和大于0,因为是升序排序的,那么表示右边太大了,需要往左移动一点,和就会小一点
right--;
} else if (sum < 0) {
// 如果和小于0,因为是升序排序的,那么表示左边太小了,需要往右移动一点,和就会大一点
left++;
}
}
}
// 返回结果
return res;
};