首页 > 其他分享 >回溯-组合

回溯-组合

时间:2022-11-01 19:11:05浏览次数:48  
标签:begin return target 组合 int candidates 回溯 path

组合问题也是需要进行穷举的,使用回溯算法正合适。

案例1:

给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。

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

注意:一般的组合中,数字是不能重复使用的,这个题目很特殊,数字可以重复使用。

1.可行解的要求是什么?

显而易见,我们找到了数组中的数字组合,加起来的和正好等于目标target,这就是一个可行解

2.递归退出的条件是什么?

有三个,其中两个是明确的①找到了可行解,②递归过程中发现target<0,

隐含的退出是for循环结束。

3.如何进行回溯

我们使用了path队列存储过程解,当需要回溯时,删掉path的最后一个元素即可。

4.如何求得不同的组合

题目中虽然明确说明元素可以重复使用,但是组合肯定是不能重复的,比如我们已经找到一个[2,2,3]作为可行解,在后面不能又找到一个[3,2,2]这样组合就重复了。

解决办法是我们定义一个begin指针,下层递归只能使用大于等于begin的元素,就不会出现上面的情况了。

class Solution {
   List<List<Integer>> res = new ArrayList<>();

    /**
     * 大佬的题解比官方的更容易理解!!
     * @param candidates
     * @param target
     * @return
     */
    public List<List<Integer>> combinationSum(int[] candidates, int target) {

        int len = candidates.length;
        if (len == 0) {
            return res;
        }
        //阶段性成果
        Deque<Integer> path = new ArrayDeque<>();
        //深度优先搜索
        dfs(candidates, target, path, 0);
        return res;
    }

    /**
     * @param candidates 候选数组
     * @param target     每减去一个元素,目标值变小
     * @param path       从根结点到叶子结点的路径,是一个栈
     * @param begin      搜索起点
     */
    private void dfs(int[] candidates, int target, Deque<Integer> path, int begin) {
        // target 为负数和 0 的时候不再产生新的孩子结点
        int len = candidates.length;
        if (target < 0) {
            return;
        }
        //产生一个有效结果
        if (target == 0) {
            res.add(new ArrayList<>(path));
            return;
        }

        // 重点理解这里从 begin 开始搜索的语意
        for (int i = begin; i < len; i++) {
            path.addLast(candidates[i]);

            // 注意:由于每一个元素可以重复使用,下一轮搜索的起点依然是 i,这里非常容易弄错
            dfs(candidates, target - candidates[i], path, i);

            // 状态重置
            path.removeLast();
        }
    }
}

案例2:

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

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

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

本题目和上一题目非常类似,区别在于 

重点:上一个题目每个元素可以用多次,这个只能用一次,而且不能包含重复的组合。

1.如何保证一个元素只使用一次

我们定义一个begin指针,下一次取数据的时候指针+1

2.如何在元素有重复的情况下保证组合是不重复的

这一点非常非常非常关键!也是难点所在!

方法就是在同一层遍历的时候,如果发现当前元素和前一个元素相同,比如223遍历到第二个2的时候,发现前面也是2,那么这个地方就需要进行剪枝。

class Solution {
    List<List<Integer>> ans = new ArrayList<>();

    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        List<Integer> path = new ArrayList<>();
        Arrays.sort(candidates);
        dfs(candidates, path, target, 0);
        return ans;
    }

    private void dfs(int[] candidates, List<Integer> path, int target, int begin) {
        if (target < 0) {
            return;
        }
        if (target == 0) {
            ans.add(new ArrayList<>(path));
            return;
        }
        int len = candidates.length;
        if (begin == len) {
            return;
        }

        for (int i = begin; i < len; i++) {
            //这一条的剪枝是关键!!!
            if (i > begin && candidates[i] == candidates[i - 1]) {
                continue;
            }
            path.add(candidates[i]);
            dfs(candidates, path, target - candidates[i], i + 1);
            path.remove(path.size() - 1);
        }
    }
}

 

标签:begin,return,target,组合,int,candidates,回溯,path
From: https://www.cnblogs.com/wangbin2188/p/16848831.html

相关文章

  • 回溯-单词搜索
    在二维数组进行单词搜索也是经典的需要采用回溯算法的问题。案例1:给定一个 mxn二维字符网格 board和一个字符串单词 word。如果 word存在于网格中,返回true;否......
  • AI人脸检测智能分析网关算法模型管理,支持自由组合算法
    AI图像识别技术是人工智能的一个重要领域,伴随着互联网技术的快速发展,图像识别技术的运用也越来越广泛。目前,基于神经网络的图像识别技术在社会生活的方方面面应用非常多。智......
  • 回溯-N皇后
    回溯算法其实就是暴力穷举算法,只不过暴力穷举采用了先拆解子问题,然后将子问题使用递归的方式进行求解,并且在不满足条件的情况下,有向上回溯的过程。许多复杂的,规模较大的问......
  • vue3-组合式api-定义响应式数据-reactive,toRefs
    <template> <div>  {{obj.name}}  {{name}}  <button@click="changeObjName">改变名字</button> </div></template><script>import{react......
  • LeetCode 236. 二叉树的最近公共祖先 - 回溯的理解
    题目https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-tree/思路自己做只摸到一些门道,还是靠随想录...代码:deflowestCommonAncestor(self,root:'......
  • 【XSY4320】Catalan(组合意义,DP,多项式)
    题面:Catalan题解:假瑞的做法orz考虑用组合意义来做,观察递推式\(f_i=\frac{1}{i}\sum_{j=0}^{i-1}f_jf_{i-j-1}\),它除了和卡特兰数递推式很像之外,还和二叉树计数的递推......
  • 英语单词的构成 一个英语单词是怎么组合的
    原文网址:http://www.tingclass.net/show-242-465038-1.html?gfh随着英语的普及,英语也成为一门很重要的外语学科,我们虽然平日里都在学习英语,但是有多少同学真正了解英语呢?......
  • CF1622D. Shuffle 题解 组合数学/枚举
    题目链接:​​https://codeforces.com/problemset/problem/1622/D​​题目大意:给定一个长度为\(n\)的01字符串\(s\),你可以对这个字符串进行最多一次操作,该次操作需要选择......
  • 【XSY3395】逃亡(概率与期望,组合数)
    首先“被经过的整点的期望个数”不好求,我们可以把它看成“每个整点被经过的概率的和”。对于某个整点,求“它被任意一个人经过的概率”不好求,我们可以求“它不被任意......
  • 一道有趣的组合数学问题
    背景:这道题原先是之前一次练习的问题,当时自己推公式推了很久最后看题解发现是一道组合数学问题,给了自己很多启发,特此记录原题链接简单描述题意就是给定一个矩形区域的......