描述
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。
输入:nums = [-1, 0, 1, 2, -1, -4]
输出:[ [-1, 0, 1], [-1, -1, 2] ]
解题思路一
根据两数求和的思路,可以将求和问题转为求差,那么可以固定一个参数,剩下的就转化为两数求和问题了
先把固定的元素给排出出来,将剩下的数组转化为二维数组的问题
求解
// 先准备两数求和
function twoSums(sums, target) {
let obj = {}
for(let i = 0; i < sums.length; i++) {
const r = target - sums[i]
if(obj[r] !== undefined) {
return [obj[r], sums[i]]
} else {
obj[sums[i]] = sums[i]
}
}
return []
}
function threeSums(nums){
let res = []
for (let i =0; i < nums.length; i++) {
const copyNums = [...nums] // 浅拷贝一份
const curNum = (copyNums || []).splice(i, 1)[0] // 拿到当前的元素
const otherTwo = twoSums(copyNums, -curNum)
if(otherTwo && otherTwo.length > 0) {
res.push([].concat(curNum, ...otherTwo))
}
}
return res
}
运行结果
很明显不符合要求,很多重复的结果,那么是否可以有优化的策略呢
解题思路二,双指针法
对于使用双指针,需要数组有序,因此先排序
function threeSums(nums) {
nums.sort()
const length = nums.length
const res = []
for(let i = 0; i < length - 2; i++) {
let j = i + 1
let k = length - 1
// 如果遇到连续元素则跳过
if (i > 0 && nums[i] === nums[i-1]) {
continue
}
while(j < k) {
if(nums[i] + nums[j] + nums[k] === 0) {
res.push([nums[i], nums[j], nums[k]])
j++
k--
while(j < k && nums[j] === nums[j-1]) {
j++
}
while(j < k && nums[k] === nums[k+1]) {
k--
}
} else if (nums[i] + nums[j] + nums[k] < 0) {
j++
while(j < k && nums[j] === nums[j-1]) {
j++
}
} else if (nums[i] + nums[j] + nums[k] > 0) {
k--
while(j < k && nums[k] === nums[k+1]) {
k--
}
}
}
}
return res
}
参考别人答案,死记硬背的。。。