代码随想录算法训练营第二十二天 | 回溯理论基础 77.组合 216.组合总和Ⅲ 17.电话号码的字母组合

server/2024/10/23 5:45:29/

回溯理论基础:

回溯效率:

回溯本质上是穷举,从所有答案中选出想要的。会增加一些剪枝的操作

回溯法解决的问题:

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

如何理解回溯:

回溯解决的问题可以抽象为树形结构,因为回溯解决的是在集合中递归查找子集,集合大小为树的宽度,递归深度为树的深度

回溯模板:

① 参数及返回值:一般返回值为void,参数是先写逻辑,需要什么参数对应填

void backtracking(参数)

② 终止条件:一般是搜索到叶子节点

if (终止条件){结果return;
}

③ 遍历过程:回溯所形成的树为m叉树,因此是先选择一个孩子节点,再进行递归调用。树中孩子节点的数量是集合的大小

for(选择本层集合中的元素){处理节点;backtracking(路径,选择列表);	//递归回溯,撤销处理结果
}

LeetCode 77.组合:

文章链接
题目链接:77.组合

思路

如下图所示,从左向右遍历,当前节点cur可选的集合为(cur, n]
在这里插入图片描述
① 参数及返回值:传入cur表示当前访问过的数,count为path中已经记录过的数,path保存路径
② 边界条件:找到叶子节点,即count = 0
③ 遍历过程:for循环遍历(cur, n],但是可以加剪枝,下图中红色部分其实不需要遍历一次
还需要的节点数量count
访问的最大值为n
因此至多访问到 n - count + 1
访问的区间为(cur, n - count + 1],又range为左闭右开
因此访问区间为[cur + 1, n - count + 2]
在这里插入图片描述

class Solution:def combine(self, n: int, k: int) -> List[List[int]]:self.n = nself.result = []self.backtracking(0, k, [])return self.resultdef backtracking(self, cur, count, path):if count == 0:self.result.append(path[:])returnfor i in range(cur + 1, self.n  - count + 2):path.append(i)self.backtracking(i, count - 1, path)path.pop()

LeetCode 216.组合Ⅲ:

文章链接
题目链接:216.组合Ⅲ

思路

和上一题思路相同,都是从左向右进行遍历
① 传入参数:cur表示当前访问的节点,subsum表示目标和(每次递归都会减去当前节点的值),path记录路径,count记录path还差多少个数
② 边界条件:访问到叶子节点

if count == 0 and subsum == 0:	# 目标叶子节点self.result.append(path[:])return
elif count == 0 or subsum == 0:		# 非目标叶子节点和剪枝(subsum为0,但是没到叶子)return

③ 递归遍历:for循环的值的范围为[cur + 1, 9],可以进行剪枝
1)可取到的最大值为min(9, subsum) = maxdigital
2)path需要取到的剩余元素个数为count,那么for循环至多到maxdigital - count + 1(maxdigital - x + 1 = count → x = maxdigital - count + 1)
又range为左闭右开区间,因此范围为[cur + 1, maxdigital - count + 2)

class Solution:def combinationSum3(self, k: int, n: int) -> List[List[int]]:self.result = []self.backtracking(0, n, [], k)return self.resultdef backtracking(self, cur, subsum, path, count):if count == 0 and subsum == 0:self.result.append(path[:])returnelif count == 0 or subsum == 0:returnmaxdigital = min(9, subsum)for i in range(cur + 1, maxdigital - count + 2):path.append(i)self.backtracking(i, subsum - i, path, count - 1)path.pop()

LeetCode 17.电话号码的字母组合:

文章链接
题目链接:17.电话号码的字母组合

思路:

  1. 回溯
    本题与上面几题不同,上面几题是在同一个集合中求组合,本题是在不同集合中求组合,如下图,每一层确定一个数字对应的字母,树的深度为数字的个数
    在这里插入图片描述
    可以使用二维数组保存数字与字母对应关系,也可以用字典/映射保存。但是都需要考虑到输入0,1,*,#按键等异常情况,面试都会问(首先要知道有这些异常,其次面试时需要考虑到)
    ① 传入参数:digits传入的字符串,index当前访问的数字,path / s记录当前保存的组合
    ② 边界条件:index如果是从0开始的,那么边界条件为index == len(digits);若index从len(digits) - 1开始,那么边界条件为index = 0 (此时添加s / path时需要进行反转)
    ③ 遍历过程:根据数字得到对应的字母集合,遍历该字母集合
"""
考虑了异常情况,使用字符串记录路径
"""
class Solution:def letterCombinations(self, digits: str) -> List[str]:if len(digits) == 0:return []self.digitsDict = {"0":"","1":"","2":"abc", "3":"def","4":"ghi","5":"jkl","6":"mno", "7":"pqrs","8":"tuv","9":"wxyz"}self.result = []self.backtracking(digits, len(digits) - 1, "")return self.resultdef backtracking(self, digits, index, s):       # index是从后往前遍历if index == -1:self.result.append(s[::-1])	# 记得反转returnletters = ""	# 不是正常情况就是异常if 2 <= int(digits[index]) <= 9:	# 正常情况letters = self.digitsDict[digits[index]]for letter in letters:s = s + letterself.backtracking(digits, index - 1, s)s = s[:-1]"""
使用list保存路径
"""
class Solution:def letterCombinations(self, digits: str) -> List[str]:if len(digits) == 0:return []self.digitsDict = {"2":"abc", "3":"def","4":"ghi","5":"jkl","6":"mno", "7":"pqrs","8":"tuv","9":"wxyz"}self.result = []self.backtracking(digits, len(digits) - 1, [])return self.resultdef backtracking(self, digits, index, path):       # index是从后往前遍历if index == -1:self.result.append("".join(path[::-1]))	# 记得反转returnletters = self.digitsDict[digits[index]]for s in letters:path.append(s)self.backtracking(digits, index - 1, path)path.pop()
  1. 不使用回溯
    直接遍历digits,使用result记录到目前已经得到的字符串,每次遍历将result中的全部元素与num对应的字母进行拼接(记得考虑异常情况
class Solution:def letterCombinations(self, digits: str) -> List[str]:if len(digits) == 0:return []digitDict = {"2":"abc","3":"def","4":"ghi","5":"jkl","6":"mno","7":"pqrs","8":"tuv","9":"wxyz"}result = [""]for num in digits:result = [s + letter for letter in digitDict[num] for s in result]return result


http://www.ppmy.cn/server/134087.html

相关文章

nginx的负载均衡配置和重定向

upstream_check模块 配置文件详情 upstream cluster1{server 10.0.0.4:80 weight1 max_fails3 fail_timeout30s;server 10.0.0.5:80 weight1 max_fsils3 fsil_tomeout;check interval3000 rise2 fall5 timeout1000 typehttp;check interval3000 rise2 fall5 timeout1000…

Java方法重载

Java方法重载是指在一个类中&#xff0c;可以声明多个方法具有相同的名称&#xff0c;但是参数列表不同&#xff08;参数类型、参数个数或者参数顺序不同&#xff09;的情况。在调用方法时&#xff0c;编译器根据参数的类型、顺序和个数来确定调用的是哪个方法。 方法重载的目…

vue3-高德地图天气小组件

效果图 使用方法 <weather-view type"rect-solid" :borderColor"[#7ACAEC, #068BBD]"></weather-view>天气图标文件夹 本来想全弄成svg动态图片的,但找了很久都没找到对应的图(只找到了几个),于是就暂时搁置了 组件全代码如下 注意getWeat…

nnUnet 大模型学习笔记(续):训练网络(3d_fullres)以及数据集标签的处理

目录 1. 数据集处理 1.1 实现脚本 1.2 json文件 2. 设置读取路径 2.1 设置路径 2.2 数据集转换 2.3 数据集预处理 2.4 训练&#xff08;3d_fullres) 3. 训练结果展示 关于nnUnet 数据集的处理和环境搭建&#xff0c;参考上文&#xff1a;第四章&#xff1a;nnUnet大模…

鸿蒙--页面跳转

效果 前言 基于Stage模型下的UIAbility开发,实现UIAbility内页面间的跳转和数据传递。 页面路由:提供通过不同的url访问不同的页面,包括跳转到应用内的指定页面、用应用内的某个页面替换当前页面、返回上一页面或指定的页面等 结构 ├──entry/src/main/ets // ArkTS代码…

Nodes 节点

Goto Tree List 树列表 Nodes 节点 Tree List 节点是组织成树状层次结构的数据行。 Add New Nodes 添加新节点 如果 Tree List 具有数据源&#xff0c;则会自动生成节点&#xff08;TreeListNode 类对象&#xff09;。要在未绑定模式下添加节点&#xff0c;请调用“树列表设…

WSL2 Linux子系统调整存储位置

WSL2 默认不支持修改Linux 安装路径&#xff0c;官方提供的方式&#xff0c;只有通过导出、导入的方式实现Linux子系统的迁移。 修改注册表的方式官方不推荐&#xff0c;没有尝试过&#xff0c;仅提供操作方式(自行评估风险&#xff0c;建议备份好数据) 1. 打开 **注册表编辑器…

多IP连接

一.关闭防火墙 systemctl stop firewalld setenforce 0 二.挂在mnt mount /dev/sr0 /mnt 三.下载nginx dnf install nginx -y 四.启动nginx协议 systemctl start nginx 五.修改协议 vim /etc/nginx/nginx.conf 在root前加#并且下一行添加 root /www:&#xff08;浏…