当前位置: 首页 > news >正文

回溯算法-数据结构与算法

学习计划:3个月内算法小成,完成leetcode hot100

当前进度:学完数组、链表、哈希表、字符串、双指针、二叉树

刷题语言:Python

时间:2025/05/19-2025/05/21,2025/06/17-

八、回溯算法

学习链接:代码随想录

1、回溯算法理论基础

题目分类

组合

组合

电话号码的字母组合
组合总和
组合总和II
组合总和III
分割分割回文串
复原IP地址
子集子集
子集II
全排列全排列
全排列II
棋盘问题N皇后
解数独
其他递增子序列(类似子集)
重新安排行程

什么是回溯法?

        回溯法也可以叫做回溯搜索法,它是一种搜索的方式。回溯是递归的副产品,只要有递归就会有回溯。所以以下讲解中,回溯函数也就是递归函数,指的都是一个函数

回溯法的效率

        回溯的本质是穷举,穷举所有可能,然后选出我们想要的答案,如果想让回溯法高效一些,可以加一些剪枝的操作,但也改不了回溯法就是穷举的本质,所以回溯法并不是什么高效的算法。

        那么既然回溯法并不高效为什么还要用它呢?

        因为没得选,一些问题能暴力搜出来就不错了,撑死了再剪枝一下,还没有更高效的解法。此时大家应该好奇了,都什么问题,这么牛逼,只能暴力搜索。

回溯法解决的问题

回溯法,一般可以解决如下几种问题:

  • 组合问题:N个数里面按一定规则找出k个数的集合
  • 切割问题:一个字符串按一定规则有几种切割方式
  • 子集问题:一个N个数的集合里有多少符合条件的子集
  • 排列问题:N个数按一定规则全排列,有几种排列方式
  • 棋盘问题:N皇后,解数独等等

如何理解回溯法

        回溯法解决的问题都可以抽象为树形结构,是的,我指的是所有回溯法的问题都可以抽象为树形结构!

        因为回溯法解决的都是在集合中递归查找子集,集合的大小就构成了树的宽度,递归的深度就构成了树的深度

        递归就要有终止条件,所以必然是一棵高度有限的树(N叉树)。

2、组合

题目:给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。你可以按 任何顺序 返回答案。

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

思路:把组合问题抽象为如下树形结构,图中可以发现n相当于树的宽度,k相当于树的深度图中每次搜索到了叶子节点,我们就找到了一个结果。

class Solution:def combine(self, n: int, k: int) -> List[List[int]]:res = []self.backtracking(n,k,1,[],res)return resdef backtracking(self,n,k,startIndex,path,res):#一共有k层for循环,每次递归就是一次for循环if len(path)==k:#终止条件res.append(path[:]) #将 path 的浅拷贝添加到列表 res 中,如果append(path),path变res中的元素也变returnfor i in range(startIndex,n+1):path.append(i) #处理节点self.backtracking(n,k,i+1,path,res)path.pop()#i=1  12 弹出2 | 13 弹出3 | 14 弹出4#i=2  23 弹出3 | 24 弹出4#i=3  34 弹出4
class Solution:def combine(self, n: int, k: int) -> List[List[int]]:res = []path = []def dfs(i):d = k-len(path) #还需要枚举的数字个数if d == 0:#结束递归res.append(path.copy())returnfor j in range(i,0,-1): #倒序枚举path.append(j)dfs(j-1)path.pop()dfs(n)#n=4   43 弹出3| 42 弹出2 | 41 弹出1 结束#n=3   32 弹出2| 31 弹出1 结束#n=2   21 弹出1 结束return res
  • 时间复杂度:分析回溯问题的时间复杂度,有一个通用公式:路径长度×搜索树的叶子数。对于本题,它等于 O(k⋅C(n,k))
  • 空间复杂度: O(n)

3、组合(剪枝优化)

class Solution:def combine(self, n: int, k: int) -> List[List[int]]:res = []self.backtracking(n,k,1,[],res)return resdef backtracking(self,n,k,startIndex,path,res):if len(path)==k:#终止条件res.append(path[:])returnfor i in range(startIndex,n-(k-len(path))+2): #优化path.append(i) self.backtracking(n,k,i+1,path,res)path.pop()

4、组合总和III

http://www.dtcms.com/a/275960.html

相关文章:

  • Pythone第二次作业
  • brpc 介绍与安装
  • Redis过期策略与内存淘汰机制面试笔记
  • 数据库连接池及其核心特点
  • AI编程下的需求规格文档的问题及新规范
  • ADSP-1802这颗ADI的最新DSP应该怎么做开发(一)
  • 【Redis实战】Widnows本地模拟Redis集群的2种方法
  • Syntax Error: TypeError: Cannot set properties of undefined (setting ‘parent‘)
  • Unity URP + XR 自定义 Skybox 在真机变黑问题全解析与解决方案(支持 Pico、Quest 等一体机)
  • Cookie、Session、Token 有什么区别?
  • Spring Boot 中使用 Lombok 进行依赖注入的示例
  • 【离线数仓项目】——电商域DWD层开发实战
  • 【C++ STL 库】解析stack、queue、priority_queue类
  • 中文多智能体金融交易决策框架-TradingAgents-CN
  • 本地安装ClaudeCode全攻略
  • 【Python】多线程详解:从基础概念到实战应用
  • 免费尝试claude code的安利,截至今天可用(7/12)
  • openGauss数据库管理实战指南——基本常用操作总结
  • AI:机器人未来的形态是什么?
  • Cisco ACI 生成Postman CSV 脚本场景
  • 死锁的避免
  • Spring Boot 应用中,配置的加载优先级
  • 锁相环初探
  • CTFHub————Web{信息泄露[Git泄露(Stash、Index)]}
  • Java 接口详解:从基础到高级,掌握面向对象设计的核心契约
  • 使用FastAdmin框架开发二
  • ollama - sqlcoder模型:面向提示词编程(根据用户信息生成sql语句并执行返回结果)
  • SQL新手入门详细教程和应用实例
  • 微信小程序121~130
  • [Vroom] 时间窗口 | 载重与货量管控 | 内部路由表示机制 | 增量式更新算法O(1)