【回溯算法】求目标和的组合方案(升级篇) ... |刷题打卡

简介: 【回溯算法】求目标和的组合方案(升级篇) ... |刷题打卡

题目描述



这是 LeetCode 上的40. 组合总和 II,难度为 Medium


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


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


说明:


  • 所有数字(包括目标数)都是正整数。
  • 解集不能包含重复的组合。


示例 1:


输入: candidates = [10,1,2,7,6,1,5], target = 8,
所求解集为:
[
  [1, 7],
  [1, 2, 5],
  [2, 6],
  [1, 1, 6]
]
复制代码


示例 2:


输入: candidates = [2,5,2,1,2], target = 5,
所求解集为:
[
  [1,2,2],
  [5]
]
复制代码


DFS + 回溯解法



这道题和 39. 组合总和(中等) 几乎一样。


唯一的不同是这题每个数只能使用一次,而「39. 组合总和(中等)」中可以使用无限次。


我们再来回顾一下应该如何快速判断一道题是否应该使用 DFS + 回溯算法来爆搜。


这个判断方法,最早三叶在 37. 解数独(困难) 讲过。


总的来说,你可以从两个方面来考虑:


  • 1. 求的是所有的方案,而不是方案数。 由于求的是所有方案,不可能有什么特别的优化,我们只能进行枚举。这时候可能的解法有动态规划、记忆化搜索、DFS + 回溯算法。
  • 2. 通常数据范围不会太大,只有几十。 如果是动态规划或是记忆化搜索的题的话,由于它们的特点在于低重复/不重复枚举,所以一般数据范围可以出到 10510^510510710^7107,而 DFS + 回溯的话,通常会限制在 30 以内。


这道题数据范围是 30 以内,而且是求所有方案。因此我们使用 DFS + 回溯来求解。

我们可以接着 39. 组合总和(中等) 的思路来修改:


  1. 由于每个数字只能使用一次,我们可以直接在 DFS 中决策某个数是用还是不用。
  2. 由于不允许重复答案,可以使用 set 来保存所有合法方案,最终再转为 list 进行返回。当然我们需要先对 cs 进行排序,确保得到的合法方案中数值都是从小到大的。这样 set 才能起到去重的作用。对于 [1,2,1][1,1,2],set 不会认为是相同的数组。


class Solution {
    public List<List<Integer>> combinationSum2(int[] cs, int t) {
        Arrays.sort(cs);
        Set<List<Integer>> ans = new HashSet<>();
        List<Integer> cur = new ArrayList<>();
        dfs(cs, t, 0, ans, cur);
        return new ArrayList<>(ans);
    }
    /**
     * cs: 原数组,从该数组进行选数
     * t: 还剩多少值需要凑成。起始值为 target ,代表还没选择任何数;当 t = 0,代表选择的数凑成了 target
     * u: 当前决策到 cs[] 中的第几位
     * ans: 最终结果集
     * cur: 当前结果集
     */
    void dfs(int[] cs, int t, int u, Set<List<Integer>> ans, List<Integer> cur) {
        if (t == 0) {
            ans.add(new ArrayList<>(cur));
            return;
        }
        if (u == cs.length || t < 0) return;
        // 使用 cs[u]
        cur.add(cs[u]);
        dfs(cs, t - cs[u], u + 1, ans, cur);
        // 进行回溯
        cur.remove(cur.size() - 1);
        // 不使用 cs[u]
        dfs(cs, t, u + 1, ans, cur);
    }
}
复制代码


  • 时间复杂度: DFS 回溯算法通常是指数级别的复杂度(因此数据范围通常为 30 以内)。这里暂定 O(n∗2n)O(n * 2^n)O(n2n)
  • 空间复杂度:同上。复杂度为 O(n∗2n)O(n * 2^n)O(n2n)


最后



这是我们「刷穿 LeetCode」系列文章的第 No.40 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先将所有不带锁的题目刷完。


在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。


为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:github.com/SharingSour…


在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。

相关文章
|
7月前
|
机器学习/深度学习 算法 C++
【DFS/回溯算法】2016年蓝桥杯真题之路径之谜详解
题目要求根据城堡北墙和西墙箭靶上的箭数,推断骑士从西北角到东南角的唯一路径。每步移动时向正北和正西各射一箭,同一格不重复经过。通过DFS回溯模拟“拔箭”过程,验证路径合法性。已知箭数约束路径唯一,最终按编号输出行走顺序。
|
8月前
|
机器学习/深度学习 算法 安全
【无人机三维路径规划】基于非支配排序的鲸鱼优化算法NSWOA与多目标螳螂搜索算法MOMSA求解无人机三维路径规划研究(Matlab代码实现)
【无人机三维路径规划】基于非支配排序的鲸鱼优化算法NSWOA与多目标螳螂搜索算法MOMSA求解无人机三维路径规划研究(Matlab代码实现)
393 5
|
8月前
|
机器学习/深度学习 算法 调度
基于NSGA-III算法求解微电网多目标优化调度研究(Matlab代码实现)
基于NSGA-III算法求解微电网多目标优化调度研究(Matlab代码实现)
309 3
|
8月前
|
机器学习/深度学习 算法 安全
【无人机三维路径规划】多目标螳螂搜索算法MOMSA与非支配排序的鲸鱼优化算法NSWOA求解无人机三维路径规划研究(Matlab代码实现)
【无人机三维路径规划】多目标螳螂搜索算法MOMSA与非支配排序的鲸鱼优化算法NSWOA求解无人机三维路径规划研究(Matlab代码实现)
286 0
|
8月前
|
机器学习/深度学习 边缘计算 监控
【创新】【微电网多目标优化调度】五种多目标优化算法(MOJS、NSGA3、MOGWO、NSWOA、MOPSO)求解微电网多目标优化调度(Matlab代码实现)
【创新】【微电网多目标优化调度】五种多目标优化算法(MOJS、NSGA3、MOGWO、NSWOA、MOPSO)求解微电网多目标优化调度(Matlab代码实现)
636 0
|
7月前
|
存储 算法 编译器
算法入门:剑指offer改编题目:查找总价格为目标值的两个商品
给定递增数组和目标值target,找出两数之和等于target的两个数字。利用双指针法,left从头、right从尾向中间逼近,根据和与target的大小关系调整指针,时间复杂度O(n),空间复杂度O(1)。找不到时返回{-1,-1}。
|
8月前
|
机器学习/深度学习 运维 算法
【微电网多目标优化调度】多目标学习者行为优化算法MOLPB求解微电网多目标优化调度研究(Matlab代码实现)
【微电网多目标优化调度】多目标学习者行为优化算法MOLPB求解微电网多目标优化调度研究(Matlab代码实现)
355 1
|
8月前
|
机器学习/深度学习 运维 算法
【储能选址定容】基于多目标粒子群算法的配电网储能选址定容(Matlab代码实现)
【储能选址定容】基于多目标粒子群算法的配电网储能选址定容(Matlab代码实现)
381 4
|
8月前
|
机器学习/深度学习 并行计算 算法
【CPOBP-NSWOA】基于豪冠猪优化BP神经网络模型的多目标鲸鱼寻优算法研究(Matlab代码实现)
【CPOBP-NSWOA】基于豪冠猪优化BP神经网络模型的多目标鲸鱼寻优算法研究(Matlab代码实现)
214 8
|
8月前
|
存储 并行计算 算法
【动态多目标优化算法】基于自适应启动策略的混合交叉动态约束多目标优化算法(MC-DCMOEA)求解CEC2023研究(Matlab代码实现)
【动态多目标优化算法】基于自适应启动策略的混合交叉动态约束多目标优化算法(MC-DCMOEA)求解CEC2023研究(Matlab代码实现)
376 4

热门文章

最新文章