15. 3Sum
对于复杂数据,先进行数据整理排序,再进行相关问题解,往往是明智之举
解题思路
- 首先通过从大到小的排序后,容易发现如果数字大于 target则直接返回 results
- 输出的是元素不能重复的,所以通过从大到小的排序后,如果发现
nums[i] === nums[i - 1]则进行跳过 - 取两个指针,一个
start = i + 1end = num.length - 1,去首尾遍历剩下的数据 - 如果
nums[i] + nums[start] + nums[end]等于 target 则 push 进 results,那么需要对数据进行去重操作,即start部分去重while (nums[start] === nums[start + 1]) start++end部分进行去重while (nums[end] === nums[end - 1]) end-- - 如果小于目标值,则去重后 start++
- 如果大于目标值,则去重后 end--
代码
function threeSum(nums) {
const results = []
// 数组小于3,直接返回
if (nums.length < 3) return results
// 从小到大排序
nums = nums.sort((a, b) => a - b)
// 设置相加后的目标值
let target = 0
for (let i = 0; i < nums.length - 2; i++) {
// 如果大于目标值,直接跳出循环
if (nums[i] > target) break
// 相同的元素直接跳过
if (i > 0 && nums[i] === nums[i - 1]) continue
// 剩下的数据首部
let start = i + 1
// 剩下的数据尾部
let end = nums.length - 1
while (start < end) {
let sum = nums[i] + nums[start] + nums[end]
if (sum === target) {
// 存储找到的值
results.push([nums[i], nums[start], nums[end]])
// 排除重复的值
while (nums[start] === nums[start + 1]) start++
while (nums[end] === nums[end - 1]) end--
// 排除重复的值后,说明start,end停留再最有一个重复的目标值,需要再进行一次移动
start++
end--
// 小于说明 start的位置取值太小
} else if (sum < target) {
while (nums[start] === nums[start + 1]) start++
start++
// 大于的话,说明 end位置取值太大
} else { // (sum > target)
while (nums[end] === nums[end - 1]) end--
end--
}
}
}
return results
};