leetcode算法-几数之和
两数之和
题目
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。 你可以按任意顺序返回答案。
解析
注意数组中同一个元素不能出现两次,我们可以时候Map映射让taget-nums[i]作为键,i作为值,如果Map映射中不存在该键,则保存与当前数匹配的值和当前数的下标,如果Map映射中有该键,则说明存在两个匹配的数,使得这两个数的和加起来等于target,然后返回在Map映射中匹配的另一个数的下标和当前数的下标
代码
var twoSum = function (nums, target) {
let map = new Map()
for (let i = 0; i < nums.length; i++) {
if (!map.has(nums[i])) {
map.set(target - nums[i], i)
} else {
return [map.get(nums[i]), i]
}
}
return []
};
三数之和
题目
给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请 你返回所有和为 0 且不重复的三元组。 注意:答案中不可以包含重复的三元组。
解析
难点来自与不能有重复的三元组,因为这里没有要求返回数组下标,所以我们可以对原数组进行排序后进行查找,这样更方便去重,使用双指针的方法,给定一个i,left和right让他们和等于0,left = i+1, right=nums.length-1接下来的解析写在代码后面更方便理解
代码
var threeSum = function (nums) {
if(nums.length<3) return []
//如果nums的数组小于三,则不符合题意,直接返回
nums.sort((a, b) => a - b)
//排序
let res = []
for (let i = 0; i < nums.length - 1; i++) {
if (i > 0 && nums[i] === nums[i - 1]) continue
//让nums[i]!==nums[i-1]。这样就不会出现重复的三元组
let l = i + 1, r = nums.length - 1
while (l < r) {
//注意这里不能l <== r 因为要求不同的三个数
let sum = nums[i] + nums[l] + nums[r]
//判断sum 如果==0这说明出现了结果,如果大于0则说明可能是nums[right]太大了,让right--,如果sum小于0,则说明可能是nums[left]太小了,让left++
if (sum === 0) {
res.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--
//这里l++, r--是为了让他们从下一个数开始
} else if (sum < 0) {
l++
} else {
r--
}
}
}
return res
};
四数之和
题目
给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):0 <= a, b, c, d < n a、b、c 和 d 互不相同
解析
四数之和的思路跟三数之和差不多,不过要注意四数之和的去重细节,以及临界条件。
代码
var fourSum = function (nums, target) {
if (nums.length < 4) return []
nums.sort((a, b) => a - b)
let res = []
for (let i = 0; i < nums.length - 2; i++) {
if (i > 0 && nums[i] === nums[i - 1]) continue
for (let j = i + 1; j < nums.length - 1; j++) {
if (j > i + 1 && nums[j] === nums[j - 1]) continue
let l = j + 1, r = nums.length - 1
while (l < r) {
let sum = nums[i] + nums[j] + nums[l] + nums[r]
if (sum === target) {
res.push([nums[i], nums[j], 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 < target) {
l++
} else {
r--
}
}
}
}
return res
}