算法小知识-------02·19-------组合总和

83 阅读2分钟

这是我参与2022首次更文挑战的第27天,活动详情查看:2022首次更文挑战

今天周六,需要给自己充充电,做上一题

组合总和

该题出自力扣的39题 —— 组合总和【中等题】

在做题先,需要先叙述关于回溯的相关思路。回溯也就是我们经常在做树的遍历时的深度遍历,dfs。所谓的回溯,也就是一头走到黑,然后再回退,另辟蹊径,再一头走到黑。直到彻底走完。

public void dfs(TreeNode node){
    if(node == null)return;
    dfs(node.left);
    System.out.println(node.val);
    dfs(node.right);
 }

这就是典型的树的前序遍历,并且用递归的方式,也就是回溯。先一头扎到节点的左子树,直到为空。然后回退,走根节点,再走右子树。

组合总和

给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。
candidates 中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。 
对于给定的输入,保证和为 target 的不同组合数少于 150 个。

  • 该题最主要的核心就是同一个数字可以无限制被选取;如果抛开这个条件,则可以直接用遍历碾压过去
  • 联想到回溯法。把数组转换为树,就很容易能够得出思路
    • 先一头扎到黑,每次直接调用dfs方法,index下标 +1
    • 再去对比,看是否符合条件
    • 最终返回ans

编码

class Solution {
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        List<List<Integer>> ans = new ArrayList<List<Integer>>();
        List<Integer> combine = new ArrayList<Integer>();
        dfs(candidates,target,0,ans,combine);
        return ans;
    }

    public void dfs(int[] candidates,int target, int idx,List<List<Integer>> ans,List<Integer> combine){
        if(idx == candidates.length)return;
        if (target == 0) {
            ans.add(new ArrayList<Integer>(combine));
            return;
        }
        // 直接跳过
        dfs(candidates, target,idx + 1, ans, combine );
        // 选择当前数
        if (target - candidates[idx] >= 0) {
            combine.add(candidates[idx]);
            dfs(candidates, target - candidates[idx],idx, ans, combine);
            combine.remove(combine.size() - 1);
        }
    }

}

image.png