【数据结构与算法】回溯法解题20240229

在这里插入图片描述


【数据结构与算法】回溯法解题20240229

  • 一、46. 全排列
    • 1、以[1,2,3]为例,抽象成树形结构
    • 2、回溯三部曲
  • 二、LCR 084. 全排列 II
    • 1、以[1,1,2]为例,抽象成树形结构
  • 三、面试题 08.07. 无重复字符串的排列组合
  • 四、面试题 08.08. 有重复字符串的排列组合

一、46. 全排列

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

示例 1:
输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]

示例 2:
输入:nums = [0,1]
输出:[[0,1],[1,0]]

示例 3:
输入:nums = [1]
输出:[[1]]

提示:
1 <= nums.length <= 6
-10 <= nums[i] <= 10
nums 中的所有整数 互不相同

1、以[1,2,3]为例,抽象成树形结构

在这里插入图片描述

2、回溯三部曲

1、递归函数参数
首先排列是有序的,也就是说 [1,2] 和 [2,1] 是两个集合,这和之前分析的子集以及组合所不同的地方。
可以看出元素1在[1,2]中已经使用过了,但是在[2,1]中还要在使用一次1,所以处理排列问题就不用使用startIndex了。
但排列问题需要一个used数组,标记已经选择的元素,如图橘黄色部分所示:

2、递归终止条件
可以看出叶子节点,就是收割结果的地方。
那么什么时候,算是到达叶子节点呢?
当收集元素的数组path的大小达到和nums数组一样大的时候,说明找到了一个全排列,也表示到达了叶子节点。

3、单层搜索的逻辑
这里和77.组合问题、131.切割问题和78.子集问题最大的不同就是for循环里不用startIndex了。
因为排列问题,每次都要从头开始搜索,例如元素1在[1,2]中已经使用过了,但是在[2,1]中还要再使用一次1。
而used数组,其实就是记录此时path里都有哪些元素使用了,一个排列里一个元素只能使用一次。

在这里插入图片描述

class S46:def func(self, nums):result = []def dfs(path, used):if len(path) == len(nums):result.append(path[:])returnfor i in range(len(nums)):if used[i] == True:continueused[i] = Truepath.append(nums[i])dfs(path, used)used[i] = Falsepath.pop()dfs([], [False] * len(nums))return resultr = S46()
nums = [1, 2, 3]
print(r.func(nums))

二、LCR 084. 全排列 II

中等
给定一个可包含重复数字的整数集合 nums ,按任意顺序 返回它所有不重复的全排列。

示例 1:
输入:nums = [1,1,2]
输出:
[[1,1,2],
[1,2,1],
[2,1,1]]

示例 2:
输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]

还要强调的是去重一定要对元素进行排序,这样我们才方便通过相邻的节点来判断是否重复使用了。

1、以[1,1,2]为例,抽象成树形结构

在这里插入图片描述
图中我们对同一树层,前一位(也就是nums[i-1])如果使用过,那么就进行去重。

一般来说:组合问题和排列问题是在树形结构的叶子节点上收集结果,而子集问题就是取树上所有节点的结果。

去重最为关键的代码为:

if i > 0 and nums[i] == nums[i - 1] and used[i - 1] == False:
class S47:def func(self,nums):nums.sort()result=[]def dfs(path,used):if len(path)==len(nums):result.append(path[:])returnfor i in range(len(nums)):#todo 如果当前值与上一个值相等,进行减枝操作;并且上一个值没有使用# 前一位是1,只有回溯,前一位才能置为0# 竖层:因为前一位是1,回溯到0 used=[1,0,0]——》used=[0,1,0]if i>0 and nums[i]==nums[i-1] and used[i-1]==False:continueif used[i]==True:   #细节:为了防止再次取当前值continueused[i]=Truepath.append(nums[i])dfs(path,used)used[i]=Falsepath.pop()dfs([],[False]*len(nums))return resultr=S47()
nums=[1,1,2]
print(r.func(nums))

三、面试题 08.07. 无重复字符串的排列组合

中等
无重复字符串的排列组合。编写一种方法,计算某字符串的所有排列组合,字符串每个字符均不相同。

示例1:
输入:S = “qwe”
输出:[“qwe”, “qew”, “wqe”, “weq”, “ewq”, “eqw”]

示例2:
输入:S = “ab”
输出:[“ab”, “ba”]
提示:
字符都是英文字母。
字符串长度在[1, 9]之间。

class S46:def func(self,nums):result=[]def dfs(nums,path,used):#终止条件if len(path)==len(nums):result.append(path[:])returnfor i in range(len(nums)):if used[i]==True:continueused[i]=Truepath.append(nums[i])dfs(nums,path,used)path.pop()used[i]=Falsedfs(nums,[],[False]*len(nums))res=[''.join(i) for i in result]return res
r=S46()
nums="ab"
print(r.func(nums))

四、面试题 08.08. 有重复字符串的排列组合

中等
有重复字符串的排列组合。编写一种方法,计算某字符串的所有排列组合。
示例1:
输入:S = “qqe”
输出:[“eqq”,“qeq”,“qqe”]

示例2:
输入:S = “ab”
输出:[“ab”, “ba”]
提示:
字符都是英文字母。
字符串长度在[1, 9]之间。

class S0808:def func(self,nums):result=[]def dfs(path,used):if len(nums)==len(path):result.append(path[:])returnfor i in range(len(nums)):if i>0 and nums[i]==nums[i-1] and used[i-1]==False:continueif used[i]==True:continueused[i]=Truepath.append(nums[i])dfs(path,used)used[i]=Falsepath.pop()dfs([],[False]*len(nums))return [''.join(i) for i in result]r=S0808()
nums="qqe"
print(r.func(nums))

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/497111.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Oracle 直接路径插入(Direct-Path Insert)

直接路径插入&#xff08;Direct Path Insert&#xff09;是Oracle一种数据加载提速技术&#xff0c;可以在使用insert语句或SQL*Loader工具大批量加载数据时使用。直接路径插入处理策略与普通insert语句完全不同&#xff0c;Oracle会通过牺牲空间&#xff0c;安全性&#xff0…

LeetCode19. 删除链表的倒数第 N 个结点(C++)

LeetCode19. 删除链表的倒数第 N 个结点 题目链接代码 题目链接 https://leetcode.cn/problems/remove-nth-node-from-end-of-list/description/ 代码 /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode() : …

DAY10-内容安全过滤技术概述

文件过滤技术流程: 应用行为控制技术具体:

npm run dev和npm run serve两个命令的区别

npm run dev和npm run serve两个命令的区别 前端开发过程中运行Vue项目的时候&#xff0c;有时候使用npm run serve命令可以启动项目&#xff0c;有时候却会报错&#xff1b;有时候使用npm run dev命令可以启动项目&#xff0c;有时候却也会报错。是什么原因造成这种情况呢&am…

如何正确处理 Go 项目中关于文件路径的问题

嗨&#xff0c;大家好&#xff01;我是波罗学。本文是系列文章 Go 技巧第十九篇&#xff0c;系列文章查看&#xff1a;Go 语言技巧。 在使用 Go 开发项目时&#xff0c;估计有不少人遇到过无法正确处理文件路径的问题&#xff0c;特别是刚从如 PHP、python 这类动态语言转向 Go…

复盘昨天的内容

vue调节css 后端做业务处理 1.分类管理 GetMapping("/queryCtc")public ApiResult queryCtc(){return ctcService.queryCtc();}/*** 修改类目信息* return*/PutMapping("/updateCtc")public ApiResult updateCtc(RequestBody ShopCtc shopCtc){return c…

Python Web开发记录 Day4:JavaScript

名人说&#xff1a;莫道桑榆晚&#xff0c;为霞尚满天。——刘禹锡&#xff08;刘梦得&#xff0c;诗豪&#xff09; 创作者&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 目录 四、JavaScript1、JavaScript-基础①JavaScript…

【AI绘画·24年1月最新】Stable Diffusion整合包安装!解压即用--秋葉aaaki 大佬的作品,试用

前言 Stable Diffusion 之前费老大的劲部署安装&#xff0c;解决报错。搞完之后&#xff0c;突然发现有个现成集成包可以用&#xff0c;真是效率高到不行&#xff0c;今天搞下来试试 我电脑配置&#xff1a; CPU: 12th Gen Intel Core™ i7-12700F 2.10 GHz 内存32G&#xff0…

【MySQL】内置函数 -- 详解

一、日期函数 日期&#xff1a;年月日时间&#xff1a;时分秒 1、获得年月日 2、获得时分秒 3、获得时间戳 4、在日期的基础上加日期 5、在日期的基础上减去时间 6、计算两个日期之间相差多少天 7、获得当前时间 ⚪练习 &#xff08;1&#xff09;记录生日 &#xff08;2&…

蓝桥杯备战刷题three(自用)

1.合法日期 #include <iostream> #include <map> #include <string> using namespace std; int main() {map<string,int>mp;int days[13]{0,31,28,31,30,31,30,31,31,30,31,30,31};for(int i1;i<12;i){for(int j1;j<days[i];j){string sto_strin…

硬件工程师入门基础知识(三)钽电容应用(二)

钽电容应用&#xff08;二&#xff09; 1.钽电容使用容量选择2.非固体电解质钽电容器使用时应注意的问题2.1 容量和损耗2.2 直流漏电流2.3 使用电压2.4 反向电压2.5 纹波电流2.6 失效率的影响因素2.7 补充说明&#xff1a; 1.钽电容使用容量选择 许多情况下&#xff0c;高能混…

Vue 3, TypeScript 和 Element UI Plus:前端开发的高级技巧与最佳实践

Vue 3、TypeScript 和 Element UI Plus 结合使用时&#xff0c;可以提供一个强大且灵活的前端开发环境。以下是一些高级用法和技巧&#xff0c;帮助你更有效地使用这些技术&#xff1a; 1. Vue 3 高级特性 Composition API 使用 setup 函数: Vue 3 引入了 Composition API&am…