LeetCode39.组合总和

LeetCode39.组合总和

题目描述

/**
     * 给定一个无重复元素的数组 candidates 和一个目标数 target ,
     * 找出 candidates 中所有可以使数字和为 target 的组合。
     * <p>
     * candidates 中的数字可以无限制重复被选取。
     * <p>
     * 说明:
     * <p>
     * 所有数字(包括 target)都是正整数。
     * 解集不能包含重复的组合。 
     */

思路分析

  1. 可以使用递归 + 回溯的思路
  2. 使用一个深度优先的递归函数,遍历候选数组,每次取出一个元素,就将这个元素添加到队列中,因为数组中的数字可以无限制的被选取,因此下一次从数组中选取数字时依旧从第一个元素开始选取
  3. 当以第一个元素作为起点的所有情况都遍历完毕后,然后遍历以第二个元素开头的所有情况,形成递归
  4. 若当前路径下所有元素的和等于target,说明找到一条路径,记录到结果集,如果所有元素的和小于target,说明已经不在满足条件,直接返回
  5. 源码见下

源码及分析

/**
     * 
     * @param candidates 候选数组
     * @param target 目标值
     * @return 返回结果集
     */
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        //数组长度
        int len = candidates.length;
        //结果集
        List<List<Integer>> res = new ArrayList<>();
        //保存每次递归的结果路径
        Deque<Integer> path = new ArrayDeque<>();
        //递归 + 回溯
        dfs(candidates, 0, len, target, path, res);
        return res;
    }

    /**
     * @param candidate 候选数组
     * @param begin     每次搜索开始的位置
     * @param len       数组长度
     * @param target    目标值
     * @param path      找到的路径
     * @param res       结果集
     */
    public void dfs(int[] candidate, int begin, int len, int target, Deque<Integer> path, List<List<Integer>> res) {
        //System.out.println(path);
        //如果搜索到target小于 0 ,说明没有找到,直接返回
        if (target < 0) {
            return;
        }
        //如果搜索到target 等于 0,说明找到一个路径,保存到结果集
        if (target == 0) {
            res.add(new ArrayList<>(path));
            return;
        }
        for (int i = begin; i < len; i++) {
            //将当前路径保存
            path.addLast(candidate[i]);
            //递归 + 回溯
            dfs(candidate, i, len, target - candidate[i], path, res);
            //状态重置
            path.removeLast();
        }
    }
posted @ 2021-06-28 09:10  mx_info  阅读(28)  评论(0编辑  收藏  举报