《算法通关之路》-chapter15回溯法

这篇具有很好参考价值的文章主要介绍了《算法通关之路》-chapter15回溯法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

《算法通关之路》学习笔记,记录一下自己的刷题过程,详细的内容请大家购买作者的书籍查阅。

全排列

力扣第46题
给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。

class Solution:
    def permute(self, nums: list[int]) -> list[list[int]]:
        
        res = list()
        used = set()
        n = len(nums)

        def dfs(path: list[int]):
            
            if len(path) == n:
                res.append(path[:]) # 加入的是拷贝不是引用
                return
            for i in range(n):
                if i not in used:
                    used.add(i)
                    path.append(nums[i])
                    dfs(path)
                    path.pop()
                    used.remove(i)
            
        dfs([])
        return res

nums = [1,2,3]
solu = Solution()
solu.permute(nums)
[[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]

全排列 II

力扣第47题
给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。

class Solution:
    def permuteUnique(self, nums: list[int]) -> list[list[int]]:

        res = list()
        used = set()
        n = len(nums)
        nums.sort() # 提前排序

        def dfs(path: list[int]):
            
            if len(path) == n:
                res.append(path[:])
                return

            for i in range(n):
                # 同一个位置数字不能相同,i-1 not in used 表明这个位置i-1已经待过
                if i > 0 and nums[i] == nums[i-1] and i-1 not in used:
                    continue 
                if i not in used:
                    used.add(i)
                    path.append(nums[i])
                    dfs(path)
                    path.pop()
                    used.remove(i)
            
        dfs([])
        return res

nums = [1,1,2]
solu = Solution()
solu.permuteUnique(nums)
[[1, 1, 2], [1, 2, 1], [2, 1, 1]]

组合总和

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

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

对于给定的输入,保证和为 target 的不同组合数少于 150 个。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/combination-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

# 无for循环写法,必须先排序
class Solution:
    def combinationSum(self, candidates: list[int], target: int) -> list[list[int]]:
        
        res = list()
        n = len(candidates)
        candidates.sort()

        def dfs(idx: int, cur: int, path: list[int]):

            if cur == 0: # 和为target
                res.append(path[:])
                return
            elif idx == n: # 遍历结束
                return
            
            if candidates[idx] <= cur:
                path.append(candidates[idx])
                dfs(idx, cur-candidates[idx], path)
                path.pop()
                dfs(idx+1, cur, path)
            else: # 没必要继续遍历
                return

        dfs(0, target, list())
        return res

candidates, target = [2,3,6,7], 7
solu = Solution()
solu.combinationSum(candidates, target)
[[2, 2, 3], [7]]
# for循环写法,是否排序都可
class Solution:
    def combinationSum(self, candidates: list[int], target: int) -> list[list[int]]:
        
        res = list()
        n = len(candidates)

        def dfs(idx: int, cur: int, path: list[int]):

            if cur == 0: # 和为target
                res.append(path[:])
                return
            
            for idx in range(idx, n):
        
                if candidates[idx] <= cur:
                    path.append(candidates[idx])
                    dfs(idx, cur-candidates[idx], path)
                    path.pop()

        dfs(0, target, [])
        return res


candidates, target = [2,3,6,7], 7
solu = Solution()
solu.combinationSum(candidates, target)
[[2, 2, 3], [7]]

组合总和 II

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

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

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

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/combination-sum-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

# 不使用used的写法,依据i > idx来判断
class Solution:
    def combinationSum2(self, candidates: list[int], target: int) -> list[list[int]]:
     
        res = list()
        n = len(candidates)
        candidates.sort()
  

        def dfs(idx: int, cur: int, path: list[int]):

            if cur == 0: # 和为target
                res.append(path[:])
                return
            
            for i in range(idx, n):
                # for循环中去重,这里意味着舍弃了i-1所以不能再加入i
                if i > idx and candidates[i] == candidates[i-1]:
                    continue
                if candidates[i] <= cur:
                    path.append(candidates[i])
                    dfs(i+1, cur-candidates[i], path) # 每次进入下一层时不再考虑当前数字,避免多次使用
                    path.pop()
                else: 
                    break

        dfs(0, target, list())
        return res

candidates, target = [10,1,2,7,6,1,5], 8
solu = Solution()
solu.combinationSum2(candidates, target)
[[1, 1, 6], [1, 2, 5], [1, 7], [2, 6]]
# 使用used的写法
class Solution:
    def combinationSum2(self, candidates: list[int], target: int) -> list[list[int]]:
     
        res = list()
        n = len(candidates)
        candidates.sort()
        used = set()
  

        def dfs(idx: int, cur: int, path: list[int]):

            if cur == 0: # 和为target
                res.append(path[:])
                return
            
            for i in range(idx, n):
                # for循环中去重,这里意味着舍弃了i-1所以不能再加入i
                if i > 0 and candidates[i] == candidates[i-1] and i-1 not in used:
                    continue
                if candidates[i] <= cur:
                    path.append(candidates[i])
                    used.add(i)
                    dfs(i+1, cur-candidates[i], path)
                    path.pop()
                    used.remove(i)
                else: 
                    break

        dfs(0, target, list())
        return res

candidates, target = [10,1,2,7,6,1,5], 8
solu = Solution()
solu.combinationSum2(candidates, target)
[[1, 1, 6], [1, 2, 5], [1, 7], [2, 6]]

子集

力扣第78题
给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。

解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。

# 不使用for循环的写法
class Solution:
    def subsets(self, nums: list[int]) -> list[list[int]]:
        res = []
        n = len(nums)

        def dfs(idx: int, path: list[int]):
            if idx == n:
                res.append(path[:])
                return
            path.append(nums[idx])
            dfs(idx+1, path)
            path.pop()
            dfs(idx+1, path)
        
        dfs(0, list())
        return res

nums = [1,2,3]
solu = Solution()
solu.subsets(nums)
[[1, 2, 3], [1, 2], [1, 3], [1], [2, 3], [2], [3], []]
# 使用for循环的写法
class Solution:
    def subsets(self, nums: list[int]) -> list[list[int]]:
        res = []
        n = len(nums)

        def dfs(idx: int, path: list[int]):

            res.append(path[:])
            for i in range(idx, n):
                path.append(nums[i])
                dfs(i+1, path)
                path.pop()
            
        dfs(0, list())
        return res

nums = [1,2,3]
solu = Solution()
solu.subsets(nums)
[[], [1], [1, 2], [1, 2, 3], [1, 3], [2], [2, 3], [3]]

子集 II

力扣第90题
给你一个整数数组 nums ,其中可能包含重复元素,请你返回该数组所有可能的子集(幂集)。

解集 不能 包含重复的子集。返回的解集中,子集可以按 任意顺序 排列。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/subsets-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

# 不使用used的写法,依据i > idx来判断
class Solution:
    def subsetsWithDup(self, nums: list[int]) -> list[list[int]]:
        res = []
        n = len(nums)
        nums.sort()

        def dfs(idx: int, path: list[int]):
            res.append(path[:])
            for i in range(idx, n):
                if i > idx and nums[i] == nums[i-1]:
                    continue
                path.append(nums[i])
                dfs(i+1, path)
                path.pop()
            
        dfs(0, list())
        return res

nums = [1,2,2]
solu = Solution()
solu.subsetsWithDup(nums)
[[], [1], [1, 2], [1, 2, 2], [2], [2, 2]]

笔记本-Github文章来源地址https://www.toymoban.com/news/detail-604235.html

到了这里,关于《算法通关之路》-chapter15回溯法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【数据库通关之路】 MySQL 全路线学习知识点梳理(中)

    本文是 MYSQL零基础小白学习 系列的第二篇文章,点此阅读 上一篇文章 文末包邮送《分布式中间件核心原理与RocketMQ最佳实践 》 (点击下方目录直达)一本,本文每+1000浏览额外加抽一人 需求 :设计包含如下信息的学生表,请注重数据类型、长度的合理性。 编号 姓名,姓名最

    2023年04月20日
    浏览(29)
  • 【数据库通关之路】 MySQL 全路线学习知识点梳理(上)

    这是一篇 MySQL 通关 硬核经验学习路线,包括数据库相关知识,SQL语句的使用,数据库约束,设计等。专为小白整理,针对数据库零基础的朋友们,手把手带你学习MySQL,让你轻松学会! 文末包邮送《WPS Office高效办公:数据处理与分析 》1本(点击下方目录直达),本文每+1000浏览

    2024年02月04日
    浏览(30)
  • Day 15 python学习笔记

    用print打印对象时,会自动调用 面向对象的三大特征:封装、继承、多态(有的人认为抽象也是) 在面向对象中,认为定义在类中的属性外界可以更改是不安全的,封装指一种安全机制,不让外界直接修改或操作属性,因此,将属性私有化(封装),不让外界访问,如果要访

    2024年02月07日
    浏览(32)
  • 算法通关存第一关------链表青铜挑战笔记

    如上代码其实就已经构造出了一个链表。 定义一个Node结点类,他有两个属性var,和next。由于next是Node类型,这时候next又会指向同为Node类型的对象,这个对象也拥有var,和next两个属性,由此构造出一个链表。 文章最后会有构造链表实例,完整代码。   2.1 插入结点 在插入链

    2024年02月15日
    浏览(30)
  • 算法通过村第十八关-回溯|青铜笔记|什么叫回溯(中篇)

    提示:阳光好的时候,会感觉还可以活很久,甚至可以活出喜悦。 --余秀华 回溯是非常重要的算法思想之一,主要解决一些暴力枚举也搞不定的问题(这里埋个坑💣)例如组合、分割、子集、棋盘等等。从性能角度来看回溯算法的效率并不是很高,但是对于暴力也解决不了

    2024年02月06日
    浏览(32)
  • Apollo决策规划算法学习Chapter3 速度规划算法

    第一章 Apollo决策规划算法基本概念 第二章 Apollo决策规划之路径规划算法 第三章 Apollo决策规划之速度规划算法 本文为第三章,主要讲解 Apollo决策规划算法中的速度规划算法,EM planner的速度规划算法同样是是通过动态规划和二次规划实现的,下面来细讲速度规划算法。 1)回

    2024年02月11日
    浏览(36)
  • C++算法学习心得六.回溯算法(1)

    回溯法也可以叫做回溯搜索法,它是一种搜索的方式。回溯是递归的副产品,只要有递归就会有回溯。 回溯的本质是穷举,穷举所有可能,然后选出我们想要的答案 回溯法解决的问题 组合问题:N个数里面按一定规则找出k个数的集合 切割问题:一个字符串按一定规则有几种切

    2024年01月16日
    浏览(27)
  • Unity学习笔记(零基础到就业)|Chapter03:C#核心

    这系列的学习笔记主要是根据唐老狮的unity实战路线课程整理的,加入了自己的一些补充和理解,该课程涉及的知识内容非常多,我并未学完,而是根据就业需求挑选学习的,也对后续框架部分进行了一些修改,希望能通过整理并时常阅读这些笔记巩固开发知识,也希望能跟

    2024年02月20日
    浏览(35)
  • leetCode 131.分割回文串 + 动态规划 + 回溯算法 + 优化 + 图解 + 笔记

    我的往期文章: leetCode 647.回文子串 动态规划 + 优化空间 / 中心扩展法 + 双指针-CSDN博客 https://blog.csdn.net/weixin_41987016/article/details/133883091?spm=1001.2014.3001.5501 leetCode 131.分割回文串 + 回溯算法 + 图解 + 笔记-CSDN博客 https://blog.csdn.net/weixin_41987016/article/details/134700907?spm=1001.2014.3001

    2024年02月05日
    浏览(41)
  • 一文搞定“Linux简单但实用的学习”两万字Linux通关笔记

    文章目录 操作系统的感念 操作系统组成 Linux系统介绍 Linux发行版 系统镜像下载 VMware安装centos7 Linux基本配置 系统基础操作规范 系统基础网络配置 系统基础命令介绍 系统目录相关命令 系统文件相关命令 VIM编辑器 系统压缩相关命令 系统搜索相关命令 系统基本优化 系统时间

    2024年02月10日
    浏览(52)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包