给定一个包含
n个整数的数组nums和一个目标值target,判断nums中是否存在x个元素,使得x1 + x2 + ...的值与target相等?找出所有满足条件且不重复的元组。
首先
我们先将这个问题简化,变成下面这个亚子
- x=1 -> 遍历
nums找到满足要求的值,然后push进数组,注意去重let result = [] let hash = {} //使用hash来对结果进行去重 for(let i = 0, len = nums.length; i < len; i++){ if(nums[i] === target && hash[nums[i]] === undefined) { result.push(nums[i]) hash[nums[i]] = true } } return result - x=2 -> 遍历两次
nums找到满足要求的值的组合,然后push进数组,注意去重还可以使用键值对象来减少一次循环let result = [] let hash = {} //使用hash来对结果进行去重 ️for(let i = 0, len = nums.length; i < len; i++){ for(let j = 0; j < len; j++){ if(nums[i] + nums[j] === target && hash[[nums[i], nums[j]]] === undefined && hash[[nums[j], nums[i]]] === undefined){ hash[[nums[i], nums[j]]] = true result.push([nums[i], nums[j]]) } } } return resultlet map = {} for(let i = 0, len = nums.length; i < len; i++){ if(map[target - nums[i]] !== undefined){ result.push([nums[i], nums[map[target - nums[i]]]]) } else{ map[nums[i]] = i } } return result - x=3 -> ······
for(){ for(){ for(){ ··· } } } return result - ······
这样看可以解决问题,但是好像不太聪明的亚子。而且如果求所有满足要求的组合,不限制组合中数字的个数就不能用这种层层for循环的解法。
进阶
-
排序+指针
这种方法适用于二、三、四层循环的优化,具体思路为:先选取一个数组中的数字,然后初始化指针来对其他数字进行遍历,找到满足的条件。
- 我们以x=3为🌰
var threeSum = function(nums, target) { let result = [], len = nums.length if(len < 3){ return result // 边界处理 } nums.sort((a, b) => a - b) // 排序 // 把L和R都设置在i的后边并且遇到值相等的就把下标往后移动 // 可以保证每次找到的满足要求的组合都是唯一的 for(let i = 0; i < len ; i++){ if(nums[i] === nums[i-1]) continue // 去重 let L = i + 1 let R = len - 1 while(L < R){ let sum = nums[i] + nums[L] + nums[R] if(sum === 0){ result.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-- } else if (sum < 0) L++ else if (sum > 0) R-- } } return result } -
回溯
如果题目要求求出所有满足要求的元组而不限制长度,我们可以采用回溯法来解决,具体思路为:原来数组中每个数字都有两种选择,
那就是当个好人或者做个卧底,,那就是被选中和不被选中,以此我们可以来构建二叉树并进行遍历找到满足要求的元组。- 递归实现如下:
var sum = function(nums, target) { let tempNums = nums.slice(), result = [], buffer = [], index = 0, hash = {} let _sum = (index, target) => { if(target === 0 && buffer.length !== 0){ result.push(buffer.slice()) } if(index === tempNums.length){ return } buffer.push(tempNums[index]) // 选中 _sum(index+1, target - tempNums[index]) buffer.pop() // 不选 _sum(index+1, target) } _sum(index, target) // 去重返回 return result.filter(_ => { _.sort((a, b) => a-b) if(hash[_] === undefined){ hash[_] = true return _ } }) }
- 递归实现如下:
最后
关于求x个数之和的问题就聊到这里,如有错误,恳请指正👀