LeetCode系列记录我学习算法的过程。
持续创作,加速成长!这是我参与「掘金日新计划 6 月更文挑战」的第 17 天,点击查看活动详情
题目
给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):
0 <= a, b, c, d < na、b、c和d互不相同nums[a] + nums[b] + nums[c] + nums[d] == target
你可以按 任意顺序 返回答案 。
示例:
输入: nums = [1,0,-1,0,-2,2], target = 0
输出: [[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]
输入: nums = [2,2,2,2,2], target = 8
输出: [[2,2,2,2]]
提示
1 <= nums.length <= 200-109 <= nums[i] <= 109-109 <= target <= 109
思路
这题我的思路和三数之和差不多,只不过多了一重循环,还有判断条件有所改变:
- 首先也是判断数组长度,不足
4直接返回空数组 - 然后进行升序排序,创建记录答案的
res及记录遍历过的组合map两个变量 - 双重循环进行遍历,进行下一步前先判断当前两数组合有没有遍历过,有则跳过,无则记录到
map - 头尾两指针指向下一坐标及尾坐标,判断四数之和与
target - 相等则记录答案,移动头尾指针并跳过相同项
- 不相等则视情况而定移动头指针或尾指针
- 当头尾指针相遇后结束本轮循环
代码实现
/**
* @param {number[]} nums
* @param {number} target
* @return {number[][]}
*/
var fourSum = function(nums, target) {
const len = nums.length
if(len < 4) return [] // 数组
nums.sort((a, b) => a - b) // 排序
const res = [], // 答案
map = new Map() // 记录遍历过的组合
// 遍历数组
for(let i = 0; i < len - 3; i++) {
const l1 = nums[i]
// 第二重遍历
for(let j = i + 1; j < len - 2; j++) {
const l2 = nums[j]
// 将当前两数组合,判断是否遍历过,是则跳入下一循环,不是则记录
const key = JSON.stringify([l1, l2])
if (map.has(key)) continue
map.set(key, true)
// 取下一下标及尾下标
let x = j + 1,
y = len - 1
while(x < y) {
// 取和
const sum = l1 + l2 + nums[x] + nums[y]
// 相等则记录答案,移动 x y 并跳过相同项
if (sum === target) {
res.push([l1, l2, nums[x], nums[y]])
do { x++ } while (nums[x] === nums[x - 1] && x < y)
do { y-- } while (nums[x] === nums[y + 1] && x < y)
} else if (sum < target) {
// 小于答案则移动 x
do { x++ } while (nums[x] === nums[x - 1] && x < y)
} else {
// 大于答案则移动 y
do { y-- } while (nums[x] === nums[y + 1] && x < y)
}
}
}
}
return res
};