「前端刷题」39. 组合总和

390 阅读1分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

题目

给定一个无重复元素的正整数数组 candidates 和一个正整数 target ,找出 candidates 中所有可以使数字和为目标数 target 的唯一组合。

candidates 中的数字可以无限制重复被选取。如果至少一个所选数字数量不同,则两种组合是唯一的。 

对于给定的输入,保证和为 target 的唯一组合数少于 150 个。

 

示例 1:

输入: candidates = [2,3,6,7], target = 7 输出: [[7],[2,2,3]]

示例 2:

输入: candidates = [2,3,5], target = 8 输出: [[2,2,2,2],[2,3,3],[3,5]]

示例 3:

输入: candidates = [2], target = 1 输出: []

示例 4:

输入: candidates = [1], target = 1 输出: [[1]]

示例 5:

输入: candidates = [1], target = 2 输出: [[1,1]]

 

提示:

  • 1 <= candidates.length <= 30
  • 1 <= candidates[i] <= 200
  • candidate 中的每个元素都是独一无二的。
  • 1 <= target <= 500

解题思路

首先,明确题目环境:

  1. 数字可重复选取
  2. candidates和target都是正整数

考虑到【求和以及解不重复】,有过3数之和的经验:

  1. 想到必须先对candidates进行排序
  2. 利用判断当前数字与track的末尾数字比较,达到去重的目的

编写特殊情况

  1. candidates.length<=0
  2. target<candidates[0]

编写回溯函数backTrack,见代码

代码

/**
 * @param {number[]} candidates
 * @param {number} target
 * @return {number[][]}
 */
//  数字可重复,全为正整数
var combinationSum = function(candidates, target) {
    let res=[]
    let len=candidates.length
    if(len<=0)return res

    candidates.sort((a,b)=>a-b)//从小到大排序

    if(candidates[0]>target)return res //特殊,arr[0]>target

    backTrack([],target)
    return res

    function backTrack(track,target){
        if(target===0){//终止条件
            res.push(track.slice())
            return
        }

        for(let num of candidates){
            if(num>target){//target决定取值范围
                break
            }

            //注意去重,【2,2,3】【2,3,2】不难发现,这一位>=上一位
            if(track.length!==0){
                if(num>=track[track.length-1]){//判断该选择是否导致路径重复
                    track.push(num)
                    backTrack(track,target-num)
                    track.pop()
                }else{//continue
                    continue
                }
            }else{//track无元素
                track.push(num)
                backTrack(track,target-num)
                track.pop()
            }
            
        }
        
    }
};

最后

曾梦想仗剑走天涯

看一看世界的繁华

年少的心总有些轻狂

终究不过是个普通人

无怨无悔我走我路