Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
前言
今天的题目为中等,对于能通过数组遍历解答的题目,如果遍历的数字过大,那么就需要去考虑如何优化时间复杂度,优化的方法很多,对于不同的情况,有不同的方法适用。
每日一题
题目为 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 = []
输出: []
示例 3:
输入: nums = [0]
输出: []
提示:
0 <= nums.length <= 3000-105 <= nums[i] <= 105
题解
数组遍历
双指针优化
题目要求出三个数,首先当然可以暴力性的三重循环遍历所有可能,但是这样太耗时,会导致超时,那么我们就需要想个方法来进行优化。
对于双重循环找满足条件的数字,马上就能够想到双指针,那么我们就可以用双指针来查找其中的两个数字,那么第三个数,我们可以将它固定,然后去寻找满足条件的后两个数,这样相当于每次只是去查找后面的两个数,只是没每次的要求都不同。
循环解题
首先我们将数组进行排序,然后就可以去固定第一位数,对后面的 n-1 个数做双指针的循环
先将数组进行排序
然后从第一个数开始固定为 i 后面的两端分别为 L 和 R
如果 i 是 大于0的,那说明不存在三数相加等于0的情况了,直接结束循环
如果三数相加的结果小于零,说明结果过小,那么 L++,反之 R++
碰到了 三数相加 等于零的情况时,说明这正是我们需要的三个数,将其加入结果数组当中
循环结束完全部的数组之后,就可以得到我们想要的答案了。
/**
* @param {number[]} nums
* @return {number[][]}
*/
var threeSum = function (nums) {
let ans = [];
const n = nums.length;
if (nums == null || n < 3) return ans;
nums.sort((a, b) => a - b);
for (let i = 0; i < n; i++) {
if (nums[i] > 0) break;
if (i > 0 && nums[i] == nums[i - 1]) continue;
let L = i + 1;
let R = n - 1;
while (L < R) {
const sum = nums[i] + nums[L] + nums[R];
if (sum == 0) {
ans.push([nums[i], nums[L], nums[R]]);
while (L < R && nums[L] == nums[L + 1]) {
L++;
}
while (L < R && nums[R] == nums[R - 1]) {
R--;
}
L++;
R--;
} else if (sum < 0) L++;
else if (sum > 0) R--;
}
}
return ans;
};