携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第17天,点击查看活动详情
三数之和
描述
有一个包含n个整数的数组nums,需要判断nums中是否存在三个元素 a,b,c ,使得a + b + c = 0 ?找出所有和为0且不重复的三元组。
结果返回二维数组。
分析
n可能小于3,那本题无解,直接返回一个一维空数组。
三个元素相加等于0,首先会想到暴力破解法,三层循环来求解,这样的时间复杂度是O(N³),不是最理想的方案。我们都知道两数求和一层循环通过Map结构即可求解,那三数之和也可参照类似思路,但具体实现不同,因为两数求和仅需要返回两者的下标即可,且只需要返回一对;三数之和不同,需要返回成对的数组值,且各成对数组不可重复。
- 初始化一个返回数组和Set,Set需要过滤掉相同待累加元素;
- 在第一层循环内,我们可以看做是两数之和运算,只是需要返回的结果形式不同,对应的实现方法不一样,并且在每次外层循环外需要把set清空,要不然会出现重复元素;
- 在第二层循环中,根据是否相等来判断,如果相等,则放入返回结果,不过是否要真正作为返回结果,还需要判断二维数组中是否已存在三者元素都相等的情况,如果存在,则不必重复推入。
程序实现
根据以上分析,程序代码实现如下:
var threeSum = function(nums) {
if (nums.length < 3) return []
let indexArr = []
let set = new Set()
// 两层循环和Map结构
for (let i = 0; i < nums.length - 1; i++) {
// 每一次外层循环,如果不清的话,可能会有重复数据
set.clear()
// 转化成两数之和
let sum = -nums[i]
for (let j = i + 1; j < nums.length; j++) {
if (set.has(sum - nums[j])) {
// 去重:先对数组进行排序
const arr = [nums[i], nums[j], sum - nums[j]].sort()
const filter = indexArr.filter(item => {
return item[0] === arr[0] && item[1] === arr[1] && item[2] === arr[2]
})
!filter.length && indexArr.push(arr)
} else {
set.add(nums[j])
}
}
}
return indexArr
};