和之前的最接近三数之和的解法差不多,多了重复值的判断
最接近三数之和
描述
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。 示例:
给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]
解法 双指针
使用嵌套三层的循环也可以解出来,但是太耗时了。
还是一样要先排序数组,保持升序。
后两层循环可以优化为双指针,当结果值大时,右边的指针向左移,当结果值小时,左边的指针向右移。
去除重复值可以看已经满足结果的下一个循环的值是不是一样的,一样的就不循环,也就不会有重复的结果了。
/**
* @param {number[]} nums
* @return {number[][]}
*/
var threeSum = function (nums) {
nums = nums.sort((a, b) => a - b)
const res = []
let res1, length = nums.length
if (length < 3) {
return []
}
for (let i = 0; i < length - 2; i++) {
// 当前循环的值的下一个值、数组的最后一个值
let j = i + 1, k = length - 1
// 跳过重复值
if (nums[i] === nums[i - 1]) {
continue
}
while (j < k) {
res1 = nums[i] + nums[j] + nums[k]
if (nums[i] / nums[k] > 0) {
break
}
if (res1 === 0) {
res.push([nums[i], nums[j], nums[k]])
while (nums[j] === nums[++j]) { } // 重复值跳过
} else if (res1 < 0) {
while (nums[j] === nums[++j]) { } // 重复值跳过
} else if (res1 > 0) {
while (nums[k] === nums[--k]) { } // 重复值跳过
}
}
}
return res
};
四数之和
如果说要解四数之和,那就只用在外面再加一层循环。让里面判断的目标值改为目标值减去一个层循环值。
/**
* @param {number[]} nums
* @param {number} target
* @return {number[][]}
*/
var fourSum = function (nums, target) {
nums = nums.sort((a, b) => a - b)
const res = []
let res1, length = nums.length
if (length < 4) {
return []
}
for (let g = 0; g < length - 3; g++) {
// 跳过重复值
if (nums[g] === nums[g - 1]) {
continue
}
// 如果接下来的最小的和大于目标值,退出
if (nums[g] + nums[g + 1] + nums[g + 2] + nums[g + 3] > target)
break;
// 如果接下来最大的和小于目标值,下一轮循环
if (nums[g] + nums[length - 1] + nums[length - 2] + nums[length - 3] < target)
continue;
const ans = target - nums[g]
// 三数之和
for (let i = g + 1; i < length - 2; i++) {
let j = i + 1, k = length - 1
if (i > g + 1 && nums[i] === nums[i - 1]) {
continue
}
while (j < k) {
res1 = nums[i] + nums[j] + nums[k]
if (res1 === ans) {
res.push([nums[g], nums[i], nums[j], nums[k]])
while (nums[j] === nums[++j]) { } // 重复值跳过
} else if (res1 < ans) {
while (nums[j] === nums[++j]) { } // 重复值跳过
} else if (res1 > ans) {
while (nums[k] === nums[--k]) { } // 重复值跳过
}
}
}
}
return res
};