1. 两数之和
给定一个整数数组 nums 和一个目标值 target ,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
示例 1:
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
示例 2:
输入:nums = [3,2,4], target = 6 输出:[1,2]
解题思路:
- 初始化一个
map = new Map() - 从第一个元素开始遍历
nums - 获取目标值与
nums[i]的差值,即j = target - nums[i],判断差值在map中是否存在 - 不存在(
map.has(j)为false) ,则将nums[i]加入到map中(key为nums[i], value为i,方便查找map中是否存在某值,并可以通过get方法直接拿到下标) - 存在(
map.has(j)),返回[map.get(j), i],求解结束 - 遍历结束,则
nums中没有符合条件的两个数,返回[]
时间复杂度:O(n)
const twoSum = function(nums, target) {
let map = new Map()
for(let i = 0; i < nums.length; i++) {
let j = target-nums[i]
if(map.has(j)) {
return [map.get(j), i]
}
map.set(nums[i], i)
}
return []
}
2.三数之和
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a ,b ,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。
注意: 答案中不可以包含重复的三元组。
示例 1:
输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
示例 2:
输入:nums = []
输出:[]
解法1:
我们可以继续按照两数之和的思路解题,遍历数组,选定一个数( nums[i] )作为三数之和的第一个数,然后题目就换成了在 i+1 到 nums.length-1 中两数之和问题。
但会出现一个问题:结果中可能会出现重复的三元组,需要去重
代码实现
function threeSum(nums) {
let set
let result = []
// 排序 目的是去重
nums.sort((a, b) => (a - b))
for(let i = 0; i < nums.length - 2; i++) {
set = new Set()
while (nums[i] === nums[i - 1]) i++ // 去重
// 第一个数
let first = nums[i]
let j = i + 1
while (j < nums.length) {
// 第三个数
let second = 0 - nums[j] - first
let third = nums[j]
if(set.has(second)) {
result.push([first, second, third])
set.add(third)
j++
while (nums[j] === nums[j - 1]) j++ // 去重
} else {
set.add(third)
j++
}
}
}
return result
}
解法2: 排序 + 双指针
解题思路:
数组先排序,排序完后遍历数组,以 nums[i] 作为第一个数 first ,以 nums[i+1] 作为第二个数 second ,将 nums[nums.length - 1] 作为第三个数 last ,判断三数之和是否为 0 ,
<0,则second往后移动一位(nums是增序排列),继续判断>0,则last往前移动一位(nums是增序排列),继续判断===0,则进入结果数组中,并且second往后移动一位,last往前移动一位,继续判断下一个元组
直至 second >= last 结束循环,此时, nums[i] 作为第一个数的所有满足条件的元组都已写入结果数组中了,继续遍历数组,直至 i === nums.length - 2 (后面需要有 second 、 last )
代码实现:
function threeSum(nums) {
if(!nums || nums.length < 3) return []
let result = [], second, last
// 排序
nums.sort((a, b) => a - b)
for (let i = 0; i < nums.length - 2 ; i++) {
if(nums[i] > 0) break
// 去重
if(i > 0 && nums[i] === nums[i-1]) continue
second = i + 1
last = nums.length - 1
while(second < last){
const sum = nums[i] + nums[second] + nums[last]
if(!sum){
// sum 为 0
result.push([nums[i], nums[second], nums[last]])
// 去重
while (second < last && nums[second] === nums[second+1]) second++
while (second < last && nums[last] === nums[last-1]) last--
second++
last--
}
sum < 0 && second ++
sum > 0 && last --
}
}
return result
}