ts算法题解(第39天)---leetcode 40. 组合总和 II

207 阅读1分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第9天,点击查看活动详情

前言

每天一道算法题,死磕算法

题目

给定一个候选人编号的集合 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。

candidates 中的每个数字在每个组合中只能使用 一次 。

注意:解集不能包含重复的组合。 

示例 1:

输入: candidates = [10,1,2,7,6,1,5], target = 8,
输出:
[
[1,1,6],
[1,2,5],
[1,7],
[2,6]
]

分析

  1. candidates是一个乱序的,所以我们要进行排序
  2. candidates 有可能为空,所以我们进行空数组判断,返回[]
  3. 因为candidates中包含重复的值,所以我们要剪枝

首先把我们的子集/组合的需要剪枝的模板拿出来

function backTrack(track:number[], nums:number[], start:number, result) { 
    // 把所有结果都放到结果中 
    result.push(track.slice()); 
    // start来控制树的生长 
    for (let i = start; i < nums.length; i++){ 
      track.push(nums[i]); 
      backTrack(track, nums, i + 1, result); 
      track.pop(); 
    } 
}

所以这个题目只和我们ts算法题解(第38天)----leetcode 77. 组合和90. 子集 II中的题目,差了一个变量路径和,也就是trackSum,只要我们用trackSum一直进行记录,就可以得到哪些track和为target了

我们直接上题解

题解

function backTrace(track:number[],nums:number[],start:number,target:number,trackSum,result):void{
  if(trackSum === target){
    result.push(track.slice());
    return;
  }
  if(trackSum > target){
    return;
  }

  for(let i = start;i<nums.length;i++){
    if(i>start&&nums[i]===nums[i-1]){
      continue;
    }
    // 做选择
    track.push(nums[i]);
    trackSum+=nums[i];
    backTrace(track,nums,i+1,target,trackSum,result);
    track.pop();
    trackSum-=nums[i];
  }
}


function combinationSum2(candidates: number[], target: number): number[][] {
  let result = [];
  if(!candidates.length){
    return result;
  }
  // 先排序,让相同的元素靠在一起
  candidates = candidates.sort();
  let track = [];
  let trackSum = 0;
  let start = 0;
  backTrace(track,candidates,start,target,trackSum,result)
  return result;
};

参考