【算法】回溯算法专题② ——组合型回溯 + 剪枝 python

news/2025/2/3 6:27:13 标签: 算法, 剪枝, python

目录

  • 前置知识
  • 进入正题
  • 小试牛刀
  • 实战演练
  • 总结


前置知识


算法】回溯算法专题① ——子集型回溯 python



进入正题


组合https://leetcode.cn/problems/combinations/submissions/596357179/


给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。

你可以按 任何顺序 返回答案。

示例 1:

输入:n = 4, k = 2
输出:
[ [2,4], [3,4], [2,3], [1,2], [1,3], [1,4],]

示例 2:

输入:n = 1, k = 1
输出:[[1]]

提示:
1 <= n <= 20
1 <= k <= n

思路:

回溯思路(选或不选 / 枚举选哪个)
剪枝(选不满k个就停止递归)


code1:

python">class Solution:
    def combine(self, n: int, k: int) -> List[List[int]]:
        ans = []
        path = []

        def dfs(i):
            # 剪枝
            if n - i + 1 + len(path) < k:  
                return

            if len(path) == k:
                ans.append(path.copy())
                return
            # 不选
            dfs(i + 1)

            # 选
            path.append(i)
            dfs(i + 1)
            path.pop()

        dfs(1)
        return ans

code2:

python">class Solution:
    def combine(self, n: int, k: int) -> List[List[int]]:
        ans = []
        path = []

        def dfs(i):
            # 剪枝
            if n - i + 1 + len(path) < k:
                return
            if len(path) == k:
                ans.append(path.copy())
                return
            # 枚举选哪个    
            for j in range(i, n + 1):
                path.append(j)
                dfs(j + 1)
                path.pop()

        dfs(1)
        return ans


小试牛刀


组合总和Ⅲ https://leetcode.cn/problems/combination-sum-iii/description/

找出所有相加之和为 n 的 k 个数的组合,且满足下列条件:
1.只使用数字1到9
2.每个数字 最多使用一次
返回 所有可能的有效组合的列表 。该列表不能包含相同的组合两次,组合可以以任何顺序返回。

示例 1:

输入: k = 3, n = 7
输出: [[1,2,4]]
解释:
1 + 2 + 4 = 7
没有其他符合的组合了。

示例 2:

输入: k = 3, n = 9
输出: [[1,2,6], [1,3,5], [2,3,4]]
解释:
1 + 2 + 6 = 9
1 + 3 + 5 = 9
2 + 3 + 4 = 9
没有其他符合的组合了。

示例 3:

输入: k = 4, n = 1
输出: []
解释: 不存在有效的组合。
在[1,9]范围内使用4个不同的数字,我们可以得到的最小和是1+2+3+4 = 10,因为10 > 1,没有有效的组合。

提示:
2 <= k <= 9
1 <= n <= 60

思路:

与上题一样的思路
回溯 + 剪枝


题解1:

python">class Solution:
    def combinationSum3(self, k: int, n: int) -> List[List[int]]:
        ans = []
        path = []

        def dfs(i):
        	# 剪枝
            if len(path) + 10 - i < k:
                return
            if sum(path) > n:
                return
                
            if len(path) == k and sum(path) == n:
                ans.append(path.copy())
                return
            # 选
            path.append(i)
            dfs(i + 1)
            path.pop()

            # 不选
            dfs(i + 1)

        dfs(1)
        return ans

题解2:

python">class Solution:
    def combinationSum3(self, k: int, n: int) -> List[List[int]]:
        ans = []
        path = []

        def dfs(i):
            # 剪枝
            if len(path) + 10 - i < k:
                return
            if sum(path) > n:
                return
                
            if len(path) == k and sum(path) == n:
                ans.append(path.copy())
                return
			# 枚举选哪个
            for j in range(i, 10):
                path.append(j)
                dfs(j + 1)
                path.pop()

        dfs(1)
        return ans

当然,我们可以在判断和是否为n时进行优化:
在dfs中传入target参数,每选一个数字 j 就把target减去 j

code:

python">class Solution:
    def combinationSum3(self, k: int, n: int) -> List[List[int]]:
        ans = []
        path = []

        def dfs(i, t):
            if len(path) + 10 - i < k:
                return
            if t < 0:
                return
            if len(path) == k and t == 0:
                ans.append(path.copy())
                return

            for j in range(i, 10):
                path.append(j)
                dfs(j + 1, t - j)
                path.pop()

        dfs(1, n)
        return ans



实战演练


括号生成 https://leetcode.cn/problems/generate-parentheses/

数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。

示例 1:

输入:n = 3
输出:[“((()))”,“(()())”,“(())()”,“()(())”,“()()()”]

示例 2:

输入:n = 1
输出:[“()”]

提示:
1 <= n <= 8

思路:

理解为填左括号, 不选理解为填右括号


题解:

python">class Solution:
    def generateParenthesis(self, n: int) -> List[str]:
        ans = []
        path = []

        def dfs(i, left, right):
            if i == 2 * n:
                ans.append("".join(path))
                return
            # 左括号数量不能超过n
            if left < n:
                path.append("(")
                dfs(i + 1, left + 1, right)
                path.pop()
            # 右括号数量不能超过左括号数量
            if right < left:
                path.append(")")
                dfs(i + 1, left, right + 1)
                path.pop()

        dfs(0, 0, 0)
        return ans


总结


剪枝是一种优化技术,用于提前终止那些不可能找到解的搜索路径,从而提高算法效率。
而组合型回溯问题常常与剪枝相结合


END
如果有更多问题或需要进一步的帮助,可以在评论区留言讨论哦!
如果喜欢的话,请给博主点个关注 谢谢


http://www.niftyadmin.cn/n/5840550.html

相关文章

RocketMQ中的NameServer主要数据结构

1.前言 NameServer是RocketMQ中的一个比较重要的组件&#xff0c;我们这篇博客针对NameSever中包含的组件进行分析&#xff0c;分析一下NameServer中包含的组件以及组件的作用。以前我有一篇博客中rocketMq源码分析之搭建本地环境-CSDN博客&#xff0c;在这篇博客中就简单看了…

【C语言设计模式学习笔记1】面向接口编程/简单工厂模式/多态

面向接口编程可以提供更高级的抽象&#xff0c;实现的时候&#xff0c;外部不需要知道内部的具体实现&#xff0c;最简单的是使用简单工厂模式来进行实现&#xff0c;比如一个Sensor具有多种表示形式&#xff0c;这时候可以在给Sensor结构体添加一个enum类型的type&#xff0c;…

【go语言】grpc 快速入门

一、什么是 grpc 和 protobuf 1.1 grpc gRPC 是由 Google 开发的一个高效、开源的远程过程调用&#xff08;RPC&#xff09;框架&#xff0c;用于在分布式系统中进行通信。它是基于 HTTP/2 协议&#xff0c;支持多种语言&#xff0c;能够让不同的系统或应用程序&#xff08;即…

【大数据技术】案例01:词频统计样例(hadoop+mapreduce+yarn)

词频统计(hadoop+mapreduce+yarn) 搭建完全分布式高可用大数据集群(VMware+CentOS+FinalShell) 搭建完全分布式高可用大数据集群(Hadoop+MapReduce+Yarn) 在阅读本文前,请确保已经阅读过以上两篇文章,成功搭建了Hadoop+MapReduce+Yarn的大数据集群环境。 写在前面 Wo…

【贪心算法篇】:“贪心”之旅--算法练习题中的智慧与策略(二)

✨感谢您阅读本篇文章&#xff0c;文章内容是个人学习笔记的整理&#xff0c;如果哪里有误的话还请您指正噢✨ ✨ 个人主页&#xff1a;余辉zmh–CSDN博客 ✨ 文章所属专栏&#xff1a;贪心算法篇–CSDN博客 文章目录 前言例题1.买卖股票的最佳时机2.买卖股票的最佳时机23.k次取…

git安装flutter

首先设置 Flutter 的镜像环境变量&#xff08;在 PowerShell 中运行&#xff09;&#xff1a; # 设置 Flutter 镜像 $env:PUB_HOSTED_URL"https://pub.flutter-io.cn" $env:FLUTTER_STORAGE_BASE_URL"https://storage.flutter-io.cn"# 将这些环境变量永久…

vscode+vue3+高得地图开发过过程中本地视频及地图json文件的发布问题

很久没发blog了&#xff0c;最近vscodevue3高得地图开发中&#xff0c;因为有开发的视频教程&#xff0c;还有地图的边界的.json文件&#xff0c;这些静态文件发布时&#xff0c;如果处理不当&#xff0c;build命令会将这些静态文件进行打包。打包后文件名变化了&#xff0c;这…

97,【5】buuctf web [极客大挑战 2020]Greatphp

进入靶场 审代码 <?php // 关闭所有 PHP 错误报告&#xff0c;防止错误信息泄露可能的安全隐患 error_reporting(0);// 定义一个名为 SYCLOVER 的类 class SYCLOVER {// 定义类的公共属性 $sycpublic $syc;// 定义类的公共属性 $loverpublic $lover;// 定义魔术方法 __wa…