算法系列--递归,回溯,剪枝的综合应用(1)

💕"对相爱的人来说,对方的心意,才是最好的房子。"💕
作者:Lvzi
文章主要内容:算法系列–递归,回溯,剪枝的综合应用(1)
在这里插入图片描述

大家好,今天为大家带来的是算法系列--递归,回溯,剪枝的综合应用(1)

1.全排列(重点)

链接:
https://leetcode.cn/problems/permutations/description/
在这里插入图片描述

分析:

1.画出决策树

所谓的决策树就是我们小时候学排列画的树状图,通过一个树枚举出所有的情况
在这里插入图片描述
画出决策树之后,分析每一层干的事情是否相同(一般都是相同的),对于本题,每一层干的事可以总结为

  • 枚举出所有符合条件的排列情况

注意:决策树画的越详细越好(包括所有不符合条件的情况也画出来),有助于我们后面设计代码

2.设计代码

设计代码主要从两个方面考虑

  1. 全局变量
  2. dfs函数

1.全局变量

模拟决策的过程,想想需要哪些变量,首先题目要求的返回值是一个二维数组,所以需要设计一个ret作为返回值,当我们在枚举出所有的情况时,要考虑到枚举的数字是否被使用,如果被使用就不能被枚举,所以要标记搜索路径上数字的使用情况,所以要创建一个布尔类型的数组,接着当我们走到叶子结点时,需要保存当前排列的情况,一共就三个数字,所以需要使用一个数组进行保存,接着当从叶子结点向上返回时,我们需要舍弃掉数组中最后一个数字,这个操作比较简单,可以直接对数组进行变动即可

  • List<List> ret: 最后的返回值,用于记录所有排列情况
  • List path: 用于记录每一次dfs的结果
  • boolean[] check : 用于标记搜索过程中数字的使用情况

2.dfs函数

和递归相同,dfs函数的设计我们只需要关注某一个子问题的具体操作即可

把数组中所有的数都枚举一遍,只要没有用过,就添加到path后面

3.细节问题

  • 剪枝:在check中被标记为true,就进行剪枝

  • 回溯:如图
    在这里插入图片描述

  • 递归出口:当path中元素的数目和nums中元素的数目相同时,递归结束,将path中的所有元素添加到ret之中

4.代码实现

class Solution {// 全局变量List<List<Integer>> ret;// 返回值List<Integer> path;// 记录搜索路径boolean[] check;// 标记是否被使用过public List<List<Integer>> permute(int[] nums) {ret = new ArrayList<>();path = new ArrayList<>();check = new boolean[nums.length];dfs(nums);return ret;}public void dfs(int[] nums) {// 递归出口if(nums.length == path.size()) {ret.add(new ArrayList<>(path));return;}// 函数体for(int i = 0; i < nums.length; i++) {if(check[i] == false) {path.add(nums[i]);check[i] = true;dfs(nums);// 回溯check[i] = false;path.remove(path.size() - 1);}}}
}

为什么不是ret.add(path);

在这里插入图片描述

2.⼦集

链接:
https://leetcode.cn/problems/subsets/description/

分析:
画决策树:

根据定义选或者不选当前数
在这里插入图片描述

每一层都在干啥
分别枚举出选当前数字选和不选当前数的所有情况

设计代码:

全局变量:模拟整个过程,需要两个变量

  • ret:接收每次搜索的结果,是最终的返回值
  • path: 表示搜索路径的结果

dfs: 需要一个数组和当前的位置(下标),因为我需要知道当前的数是谁

细节问题:

  • 剪枝:不需要
  • 回溯:只有当选择选当前数的情况时,在返回的时候需要删除这个数
  • 递归出口:当pos走到n.length时表示数组遍历完毕,结束递归,将path添加进ret之中

代码:

class Solution {// 全局变量List<List<Integer>> ret;List<Integer> path;public List<List<Integer>> subsets(int[] nums) {ret = new ArrayList<>();path = new ArrayList<>();dfs(nums,0);return ret;}public void dfs(int[] nums,int pos) {// 递归出口if(pos == nums.length) {ret.add(new ArrayList<>(path));return;}// 选path.add(nums[pos]);dfs(nums,pos + 1);path.remove(path.size() - 1);// 回溯// 不选dfs(nums,pos + 1);}
}

这种决策树的遍历类似于二叉树遍历中的后序遍历

第二种决策树

在这里插入图片描述

以当前位置的值为起始位置,枚举出后面所有的数字的情况

class Solution {// 全局变量List<List<Integer>> ret;List<Integer> path;public List<List<Integer>> subsets(int[] nums) {ret = new ArrayList<>();path = new ArrayList<>();dfs(nums,0);return ret;}public void dfs(int[] nums,int pos) {// 这个遍历类似于前序遍历  根左右ret.add(new ArrayList<>(path));// 刚进来的时候path为空 空集也是子集的一种// 从当前位置一直遍历到结束for(int i = pos; i < nums.length; i++) {path.add(nums[i]);dfs(nums,i+1);path.remove(path.size() - 1);// 回溯}}
}

这种遍历的方式类似于二叉树遍历中的前序遍历,先打印根节点的值,再去遍历左右子树

总结:

  1. 画出具体详细的决策树,模拟每一步都是在干啥,明确操作
  2. 设计代码,具体来说是要设计出需要的全局变量和dfs,设计dfs和我们之前递归过程中设计函数头,函数体,递归出口一样,这不过这里的逻辑会更加的复杂一点
  3. 注意细节问题:主要从两个方面考虑
    • 剪枝
    • 回溯

3.找出所有⼦集的异或总和再求和

链接:
https://leetcode.cn/problems/sum-of-all-subset-xor-totals/

分析:
在这里插入图片描述

代码:

class Solution {// 全局变量int ret;int path;public int subsetXORSum(int[] nums) {dfs(nums,0);return ret;}public void dfs(int[] nums,int pos) {ret += path;for(int i = pos; i < nums.length; i++) {path ^= nums[i];dfs(nums,i + 1);// 递归下一个位置path ^= nums[i];// 回溯}}
}

注意这里面利用了^运算的性质,a ^ a = 0

还是那句话,画出决策树一切都好办!!!

四.全排列II

链接:
https://leetcode.cn/problems/permutations-ii/

分析:

相较于全排列I多了个限制条件不能有重复的组合出现,那么只需分析出所有的不合法的情况即可
1.

  1. 同一层中(同一位置比如选择第一个位置的数),不能选择重复的数字
  2. 和全排列I一样,不能选择已经使用过的数字

对于2的处理和全排列I的处理方式相同,使用一个布尔类型的check数组标记即可,对于1需要判断出 不合法的数据,首先要和前面的数字相同nums[i] == nums[i - 1],i不能越界i != 0,其次上述两个条件还不能完全判定出是不合法的数据,还必须要保证前一个数字是同一层的,check[i - 1] == false

总结来说就是:

  1. nums[i] == nums[i-1] && 在同一层–>不合法数据–>不能dfs
  2. nums[i] == nums[i-1] && 不在同一层–>合法数据–>能dfs

此外,为了保证相同的数据是紧挨着的,还需要进行排序

代码:

class Solution {// 全局变量List<List<Integer>> ret;// 返回值List<Integer> path;// 记录搜索路径boolean[] check;// 标记是否被使用过public List<List<Integer>> permuteUnique(int[] nums) {ret = new ArrayList<>();path = new ArrayList<>();check = new boolean[nums.length];Arrays.sort(nums);dfs(nums);return ret;}public void dfs(int[] nums) {// 递归出口if(path.size() == nums.length) {ret.add(new ArrayList<>(path));return;}// 函数体for(int i = 0; i < nums.length; i++) {// 剪枝  不合法的数据if(check[i] == true || (i != 0 && nums[i] == nums[i - 1] && check[i - 1] == false)) {continue;}path.add(nums[i]);check[i] = true;dfs(nums);// 回溯check[i] = false;path.remove(path.size() - 1);}}
}

5.电话号码的字⺟组合

链接:
https://leetcode.cn/problems/letter-combinations-of-a-phone-number/
分析:

每一层所做的事情:

  • 枚举出当前数字对应的字符串中所有的字符

设计代码:
1.全局变量
ret:返回值
path
string[] map:映射关系

2.dfs(digits,pos)
pos表示digits中字符的下标
递归出口:
走到最后一个节点的位置

回溯:
删除最后添加的数字

剪枝:无

在这里插入图片描述
代码:

class Solution {List<String> ret;// 返回值StringBuffer path;// 记录搜索路径String[] map= {"","","abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};// 建立映射关系public List<String> letterCombinations(String digits) {ret = new ArrayList<>();path = new StringBuffer();if(digits.length() == 0) return ret;// 处理为空的情况dfs(digits,0);return ret;}private void dfs(String digits, int pos) {if(pos == digits.length()) {// 递归出口ret.add(path.toString());return;}String s = map[digits.charAt(pos) - '0'];// 获取当前层的字符串for(int i = 0; i < s.length(); i++) {path.append(s.charAt(i));// 追加字符dfs(digits, pos + 1);path.deleteCharAt(path.length() - 1);// 回溯}}
}

dfs是往下,是递归,每一层是要做的事情是子问题

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

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

相关文章

量化交易入门(三十八)CCI指标Python实现和回测

今天我们先单纯用CCI指标来完成策略的编写&#xff0c;后续我们会改进这个策略&#xff0c;将CCI指标和前面讲到的MACD和RSI相结合来优化&#xff0c;看看我们优化后的效果会不会更好。 一、量化策略 CCI指标在量化交易中的策略&#xff1a; 在以下情况下生成买入信号&#…

《第3选择》解决所有难题的关键思维 - 三余书屋 3ysw.net

第3选择&#xff1a;解决所有难题的关键思维 《第3选择》解决所有难题的关键思维&#xff0c;面对两难困境&#xff0c;从冲突中找到互相协同的出路 你好&#xff0c;今天我们要聊的这本书是《第3选择》&#xff0c;它出自美国著名作家史蒂芬科维之手。科维是国际上非常知名的…

RPA-财务对账邮件应用自动化(客户对账机器人)

《财务对账邮件应用自动化》&#xff0c;将会使用邮箱的SMTP服务&#xff0c;小北把资源包绑定在这篇博客了 Uibot (RPA设计软件)———机器人的小项目友友们可以参考小北的课前材料五博客~ (本博客中会有部分课程ppt截屏,如有侵权请及请及时与小北我取得联系~&#xff09; …

MySQL常见故障案例与优化介绍

前言 MySQL故障排查的意义在于及时识别并解决数据库系统中的问题&#xff0c;确保数据的完整性和可靠性&#xff1b;而性能优化则旨在提高数据库系统的效率和响应速度&#xff0c;从而提升用户体验和系统整体性能。这两方面的工作都对于保证数据库系统稳定运行、提升业务效率和…

1.5编写一个程序,输入梯形的上底,下底和高,输出梯形的面积。

1、编写一个程序,输入梯形的上底,下底和高,输出梯形的面积。 package com.kangning.web.controller.system;import java.util.Scanner;/*** 编写一个程序,输入梯形的上底,下底和高,输出梯形的面积。*/ public class CountArea {public static void main(String[] args) …

【智能家居项目】RT-Thread版本——DHT11获取温湿度 | MQTT上传到服务器 | 服务器控制外设

&#x1f431;作者&#xff1a;一只大喵咪1201 &#x1f431;专栏&#xff1a;《智能家居项目》 &#x1f525;格言&#xff1a;你只管努力&#xff0c;剩下的交给时间&#xff01; 这篇文章中&#xff0c;本喵将使用RT-Thread Studio来实现这个智能家居的项目&#xff0c;最终…

使用Git处理Github中提交有冲突的pull request

前言&#xff1a; 为什么要写这篇文章&#xff0c;因为前段时间有一个开源的github中的项目有一个朋友提交了一个pr看了下是帮忙优化了下代码&#xff08;十分感谢这位网友&#xff09;。但是他提交的pr刚好和我的项目有许多的冲突导致无法自动合并&#xff0c;在github中提示…

C++入门(2)

目录 3. C输入&输出 4. 缺省(默认)参数 4.1 缺省参数概念 4.2 缺省参数分类 全缺省参数 半缺省参数 5. 函数重载 5.1 函数重载概念 6. 引用 6.1 引用概念 6.2 引用特性 6.3 常引用 6.4 使用场景 6.5 传值、传引用效率比较 6.5.1 值和引用的作为返回值类型的性能比较 6.6 引…

一文入门Ubuntu22

目录 1.安装Ubuntu22 2.常用目录 3.常用指令 1.sudo 超级用户权限运行命令 2.ls 罗列当前文件信息 3.文件目录相关&#xff1a; 1.cd改变工作路径&#xff1a; 2.pwd 3.创建目录和文件&#xff1a; 4.which 5.ps 6.kill 7.ping 4.用户相关 5.ssh与scp 6.服务相关…

鸿蒙(HarmonyOS)ArkTs语言基础教程开发准备

本文档适用于HarmonyOS应用开发的初学者。通过构建一个简单的具有页面跳转/返回功能的应用&#xff08;如下图所示&#xff09;&#xff0c;快速了解工程目录的主要文件&#xff0c;熟悉HarmonyOS应用开发流程。 在开始之前&#xff0c;您需要了解有关HarmonyOS应用的一些基本概…

缺陷检测项目 | 使用小数据集训练实现锅炉水冷壁管表面视觉缺陷检测

项目应用场景 面向锅炉水冷璧管表面视觉缺陷检测场景&#xff0c;项目支持训练&#xff0c;使用小数据集就能够实现很好的缺陷检测效果。 项目效果&#xff1a; 项目细节 > 具体参见项目 README.md (1) 安装依赖&#xff0c;包括 gcForest、AutoKeras&#xff0c;然后安装其…

快速上手Pytrch爬虫之爬取某应图片壁纸

一、前置知识 1 爬虫简介 网络爬虫&#xff08;又被称作网络蜘蛛、网络机器人&#xff0c;在某些社区中也经常被称为网页追逐者)可以按照指定的规则&#xff08;网络爬虫的算法&#xff09;自动浏览或抓取网络中的信息。 1.1 Web网页存在方式 表层网页指的是不需要提交表单&…

JavaEE初阶之线程安全(一)

目录 题外话 正题 1.线程调度是随机的 2.修改共享数据 知识点 线程同步机制 线程异步机制 举例说明 synchronized() 知识点 举例说明 举例代码详解 死锁 举个例子: 代码 小结 题外话 这两天忽冷忽热的感冒了,昨天状态特别不好断更了一天,今天继续加油! 我会把…

远控桌面多任务并发文件保密传输

远程桌面文件传输是一个重要的功能&#xff0c;大多数远控都是用的桌面程序模式&#xff0c;利用系统自带复制粘贴拖拽文件拷贝功能&#xff0c;做一个ole调用对接&#xff0c;可以将很多控制权交给操作系统。 但我做的是浏览器版&#xff0c;浏览器是沙盒原理&#xff0c;为了…

LeetCode 738. 单调递增的数字

当且仅当每个相邻位数上的数字 x 和 y 满足 x < y 时&#xff0c;我们称这个整数是单调递增的。 给定一个整数 n &#xff0c;返回 小于或等于 n 的最大数字&#xff0c;且数字呈 单调递增 。 示例 1: 输入: n 10 输出: 9示例 2: 输入: n 1234 输出: 1234示例 3: 输入…

交通标志识别项目 | 基于Tensorflow+SSD实现道路交通标志识别

项目应用场景 面向智能驾驶或自动驾驶场景道路道路交通标志的识别&#xff0c;在交通标志识别的基础上为下一步的智能决策提供前提 项目效果&#xff1a; 项目细节 > 具体参见项目 README.md (1) 安装依赖 Python3.5、TensorFlow v0.12.0、Pickle、OpenCV-Python、Matplotl…

python笔记(9)Dictionary(字典)

目录 创建字典 取值 修改字典 删除 内置函数和方法 创建字典 字典键值和value用&#xff1a;隔开&#xff0c;键值是不可变的&#xff0c;而且必须是唯一的&#xff0c;值可以变&#xff0c;可以是任意类型 dict {key1 : value1, key2 : value2 } 1&#xff09;不允许同…

【面试八股总结】传输控制协议TCP(一)

一、什么是TCP协议 TCP是传输控制协议Transmission Control Protocol TCP 是面向连接的、可靠的、基于字节流的传输层通信协议。 面向连接的&#xff1a;每条TCP连接杜只能有两个端点&#xff0c;每一条TCP连接只能是点对点的&#xff08;一对一&#xff09;可靠的&#xff1a…

学习Linux推荐的书籍

我记得有人曾经说过&#xff0c;征服一个男人最好的途径就是抓住他的胃。 ‍‍‍‍ 学习Linux&#xff0c;最重要的就是要先搞懂Linux是啥&#xff0c;有啥&#xff0c;为啥&#xff1f;‍‍‍‍‍‍‍‍‍‍‍‍‍ 所以&#xff0c;我推荐的第一本书就是-《Unix编程艺术》。…