Day28:回溯法 491.递增子序列 46.全排列 47.全排列 II 332.重新安排行程 51. N皇后 37. 解数独 蓝桥杯 与或异或

491. 非递减子序列

给你一个整数数组 nums ,找出并返回所有该数组中不同的递增子序列,递增子序列中 至少有两个元素 。你可以按 任意顺序 返回答案。

数组中可能含有重复元素,如出现两个整数相等,也可以视作递增序列的一种特殊情况。

示例 1:

输入:nums = [4,6,7,7]
输出:[[4,6],[4,6,7],[4,6,7,7],[4,7],[4,7,7],[6,7],[6,7,7],[7,7]]

示例 2:

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

提示:

  • 1 <= nums.length <= 15
  • -100 <= nums[i] <= 100

思路:

本题和求子集相似,要求取有序子集,但子集不能重复,所以就不能将原数组排序后取子集实现去重,本题也是同一父节点下的同层上使用过的元素就不能再使用了

递归三部曲:

1.确定返回值和参数的类型

定义两个全局变量

List<List<Integer>> result;记录所有结点
    List<Integer> node;记录当前结点

返回值为void,在递归过程中更高全局变量

2.确定递归结束条件

本题其实类似求子集问题,也是要遍历树形结构找每一个节点,但本题收集结果有所不同,题目要求递增子序列大小至少为2

  if(startIndex>nums.length)
        return;
这行代码可以省略,因为startIndex在递归过程中会加1,不会无限递归下去(进不去for循环) 

3.确定单层逻辑

 同一父节点下的同层上使用过的元素就不能再使用了,我们使用set对本层元素去重,注意set只负责本层,所以进入下一层需要清空

将个数大于1的node加入到result

对本层元素去重

递归找到所有node

代码参考:
 

class Solution {List<List<Integer>> result = new  LinkedList<>();List<Integer> path = new LinkedList<>(); public List<List<Integer>> findSubsequences(int[] nums) {backTracking(nums,0);return result;}public void backTracking(int[] nums,int startIndex){if(path.size()>1)result.add(new LinkedList<>(path));if(startIndex == nums.length){return;}Set<Integer> hashSet= new HashSet<>();for(int i=startIndex;i<nums.length;i++){if(!path.isEmpty()&&nums[i]<path.get(path.size()-1)||hashSet.contains(nums[i])){continue;}     hashSet.add(nums[i]);path.add(nums[i]);backTracking(nums,i+1);path.removeLast();}}}

 


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 中的所有整数 互不相同

思路:

思路:用回溯法收集叶节点,用uesd数组记录路径上哪些数字已经使用,实现路径去重,这里就不是树层去重了

递归三部曲:

1.确定返回值和参数的类型

定义两个全局变量List<List<Integer>> result=new ArrayList<>();记录结果集
    List<Integer>path=new LinkedList<>();记录递归路径,也就是全排列的过程

返回值为void,传入需要排列 的数组nums,和数组used(记录递归过程中哪些数被用掉了,实现路径去重)

2.确定递归结束条件

  if(nums.length==path.size()){
            result.add(new ArrayList<>(path));
            return;
        }

nums.length==path.size()时到达叶节点,也就是找到一组全排列了

3.确定单层逻辑

将路径上没用过的数加入路径

代码:

 

class Solution {List<List<Integer>>  result = new LinkedList<>();List<Integer> path = new LinkedList<>();public List<List<Integer>> permute(int[] nums) {boolean[] used = new boolean[nums.length];backTracking(nums,used);return result;}public void backTracking(int[] nums,boolean[] used){if(path.size()==nums.length){result.add(new LinkedList(path));}for(int i=0;i<nums.length;i++){if(used[i]){continue;}path.add(nums[i]);used[i]=true;backTracking(nums,used);used[i]=false;path.removeLast();}}
}

47. 全排列 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 <= nums.length <= 8
  • -10 <= nums[i] <= 10

思路:本题与上一题区别在于,序列nums包含重复数字, 本题该如何去重 呢?

先将数组排序,让相同的数字排在一起,实现树层去重,利用used数组实现路径去重

i>0&&nums[i-1]==nums[i]&&!used[i-1]:说明在同一层使用了,注意这里的used[i-1]必须为false,只有这样两个相同的数才会出现在同一层

used[i]:说明该数在路径中已经使用了,不能再使用了

代码:

 if(i>0&&nums[i-1]==nums[i]&&!used[i-1]||used[i]){
                continue;
            }

代码参考:

class Solution {List<List<Integer>> result= new LinkedList<>();List<Integer> path= new LinkedList<>();public List<List<Integer>> permuteUnique(int[] nums) {boolean[] used = new boolean[nums.length];Arrays.sort(nums);backTracking(nums,used);return result;}public void backTracking(int[] nums,boolean[] used){if(nums.length==path.size()){result.add(new LinkedList<>(path));return;}for(int i=0;i<nums.length;i++){if(i>0&&nums[i-1]==nums[i]&&!used[i-1]||used[i]){continue;}used[i]=true;path.add(nums[i]);backTracking(nums,used);used[i]=false;path.removeLast();}}
}

332. 重新安排行程

给你一份航线列表 tickets ,其中 tickets[i] = [fromi, toi] 表示飞机出发和降落的机场地点。请你对该行程进行重新规划排序。

所有这些机票都属于一个从 JFK(肯尼迪国际机场)出发的先生,所以该行程必须从 JFK 开始。如果存在多种有效的行程,请你按字典排序返回最小的行程组合。

  • 例如,行程 ["JFK", "LGA"] 与 ["JFK", "LGB"] 相比就更小,排序更靠前。

假定所有机票至少存在一种合理的行程。且所有的机票 必须都用一次 且 只能用一次。

示例 1:

输入:tickets = [["MUC","LHR"],["JFK","MUC"],["SFO","SJC"],["LHR","SFO"]]
输出:["JFK","MUC","LHR","SFO","SJC"]

示例 2:

输入:tickets = [["JFK","SFO"],["JFK","ATL"],["SFO","ATL"],["ATL","JFK"],["ATL","SFO"]]
输出:["JFK","ATL","JFK","SFO","ATL","SFO"]
解释:另一种有效的行程是 ["JFK","SFO","ATL","JFK","ATL","SFO"] ,但是它字典排序更大更靠后。

提示:

  • 1 <= tickets.length <= 300
  • tickets[i].length == 2
  • fromi.length == 3
  • toi.length == 3
  • fromi 和 toi 由大写英文字母组成
  • fromi != toi

思路:

本题用回溯法,遍历所有的票的使用顺序,由于所有机票至少存在一种合理的行程,我们先将票按照起始位置的开头字母小的排序,递归过程中找到其中一种合理行程就返回,该行程一定是字典排序更小的行程。

递归三部曲:

1.确定返回值和参数的类型

使用全局变量保存结果 ,参数传入所有的票(List<List<String>> tickets),和每张票的使用情况(used[])

由于只取第一个结果,所有返回值类型设置为boolean类型,当找到第一个结果时,就返回true

 List<String> path=new LinkedList<>();
    List<String> result;
boolean travel(List<List<String>> tickets,boolean used[])
2.确定递归结束条件

当记录路径的数组的长度==票的长度+1,说明合理用完了所有票,找到了合理旅游路径,结束递归

   if(path.size()==tickets.size()+1){
            result=new ArrayList<>(path);
            return true;
        }
3.单层递归逻辑

递归找到所有方案

 for(int i=0;i<tickets.size();i++){
            if(!used[i]&&path.get(path.size()-1).equals(tickets.get(i).get(0))){
              path.add(tickets.get(i).get(1));
              used[i]=true;
              //找到第一个方案,结束递归
            if( travel(tickets,used))return true;
              path.remove(path.size()-1);
              used[i]=false;
            }
 
        }
        return false;
总体代码:

class Solution {List<String> path=new LinkedList<>();List<String> result;public List<String> findItinerary(List<List<String>> tickets) {boolean[] used=new boolean[tickets.size()];//给票排序Collections.sort(tickets,(a,b)->a.get(1).compareTo(b.get(1)));path.add("JFK");travel(tickets,used);return result;}boolean travel(List<List<String>> tickets,boolean used[]){if(path.size()==tickets.size()+1){result=new ArrayList<>(path);return true;}for(int i=0;i<tickets.size();i++){if(!used[i]&&path.get(path.size()-1).equals(tickets.get(i).get(0))){path.add(tickets.get(i).get(1));used[i]=true;//找到第一个方案,结束递归if( travel(tickets,used))return true;path.remove(path.size()-1);used[i]=false;}}return false;}
}


使用本方法因为排序的原因会出现超时 

改进方法:

用Map<出发机场, Map<到达机场, 航班次数>> map来记录车票,Map<到达机场, 航班次数>为升序TreeMap

class Solution {private Deque<String> path = new LinkedList<>();//双端队列,用来存储飞行路径private Map<String,Map<String,Integer>> map = new HashMap<>();//hashmap存储一个其他到其他地方的票数public List<String> findItinerary(List<List<String>> tickets) {for(int i=0;i<tickets.size();i++){//统计每个出发地到目的地的票数if(map.containsKey(tickets.get(i).get(0))){Map<String,Integer> temp= map.get(tickets.get(i).get(0));//获取目的地们与其对应的票数temp.put(tickets.get(i).get(1),temp.getOrDefault(tickets.get(i).get(1),0)+1);map.put(tickets.get(i).get(0),temp);}else{Map temp = new TreeMap<>();temp.put(tickets.get(i).get(1),1);map.put(tickets.get(i).get(0),temp);}}path.add("JFK");backTracking(tickets.size());return new LinkedList( path);}public boolean backTracking(int tickets){if(path.size()==tickets+1){return true;}String start =  path.getLast();//取出同一出发地点的各个机票的目的地和对应的票数if(map.get(start)!=null)for(Map.Entry<String, Integer> target : map.get(start).entrySet()){int  times= target.getValue();if(times>0){path.add(target.getKey());target.setValue(times-1);if( backTracking(tickets)){return true;}path.removeLast();target.setValue(times);}}return false;}
}

51. N 皇后

按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。

n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。

给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。

每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。

示例 1:

输入:n = 4
输出:[[".Q..","...Q","Q...","..Q."],["..Q.","Q...","...Q",".Q.."]]
解释:如上图所示,4 皇后问题存在两个不同的解法。

示例 2:

输入:n = 1
输出:[["Q"]]

提示:

  • 1 <= n <= 9

皇后们的约束条件:

  1. 不能同行
  2. 不能同列
  3. 不能同斜线

 思路:用回溯法,遍历出所有可以放置的可能性

递归三部曲:

1.确定返回值和参数类型

要把所有能摆放的位置都得出,用全局变量public List<List<String>> result=new ArrayList<>();记录所有合理的棋盘,返回值为void,传入棋盘(char[][] chessboard),要放置的皇后在哪一行(int row),棋盘的宽度(n);

 public void backTracking(int n,int row,char[][] chessboard)

2.确定递归结束条件

当row==n时,说明所有行都放置了皇后,找到了一种合理放法,将该棋盘存入result中,递归结束

 if(row==n){
           List<String> temp= array2List(chessboard);
           result.add(temp);
           return;
       }

3.确定单层递归逻辑

遍历该行的每一个位置并检查其合理性,如果合理,进入下一行棋盘的摆放

for(int i=0;i<n;i++){
        //如果当前位置合法,就递归放下一行
        if(isVaild(chessboard,row,i,n)){
        chessboard[row][i]='Q';
        backTracking(n,row+1,chessboard);
        chessboard[row][i]='.';
        }
       }

class Solution {List<List<String>> result = new LinkedList<>();List<String> board = new LinkedList<>();public List<List<String>> solveNQueens(int n) {char[][] chessboard = new char[n][n];for(char[] c:chessboard){Arrays.fill(c,'.');}backTracking(n,0,chessboard);return result;}public void backTracking(int n,int row,char[][] chessboard){if(row==chessboard.length){List<String> temp= array2List(chessboard);result.add(temp);return;}for(int i=0;i<chessboard.length;i++){if(isVaild(n,chessboard,row,i)){chessboard[row][i]='Q';backTracking(n,row+1,chessboard);chessboard[row][i]='.';}}}//将数组转为listList<String> array2List(char[][] chessboard){List<String> result=new ArrayList<>();for(int i=0;i<chessboard.length;i++){StringBuilder temp=new StringBuilder();for(int j=0;j<chessboard[0].length;j++){temp.append(chessboard[i][j]);}result.add(temp.toString());}return result;}public boolean isVaild(int n,char[][] chessboard,int row,int col){//检查列for(int i=row;i>=0;i--){if(chessboard[i][col]=='Q'){return false;}}//45°角for(int i=row-1,j=col+1;i>=0&&j<n;i--,j++){if(chessboard[i][j]=='Q'){return false;}}//135°for(int i=row-1,j=col-1;i>=0&&j>=0;i--,j--){if(chessboard[i][j]=='Q'){return false;}}return true;}
}

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

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

相关文章

双指针问题2

文章目录 1. 有效三角形的个数&#xff08;611&#xff09;2. 查找总价格为目标值的两个商品&#xff08;LCR179&#xff09;3. 三数之和&#xff08;15&#xff09;4. 四数之和&#xff08;18&#xff09; 1. 有效三角形的个数&#xff08;611&#xff09; 题目描述&#xff…

逻辑蕴含、函数依赖集的闭包、Armstrong公理、属性集闭包

一、引言 Armstrong公理-从给定的函数依赖集得到关系模式的完整依赖集 二、逻辑蕴含 1、定义 设F是关系模式R上的函数依赖集&#xff0c;X、Y是R的属性子集&#xff0c;对于R的每个满足F的关系实例r&#xff0c;若函数 依赖都成立&#xff0c;则称F逻辑蕴含。 记为&#…

Mamaba3--RNN、状态方程、勒让德多项式

Mamaba3–RNN、状态方程、勒让德多项式 一、简单回顾 在Mamba1和Mamba2中分别介绍了RNN和状态方程。 下面从两个图和两个公式出发&#xff0c;对RNN和状态方程做简单的回顾&#xff1a; R N N : s t W s t − 1 U x t &#xff1b; O t V s t RNN: s_t Ws_{t-1}Ux_t&…

shadertoy-安装和使用

一、安装vscode 安装vscode流程 二、安装插件 1.安装glsl编辑插件 2.安装shader toy插件 三、创建glsl文件 test.glsl文件 float Grid(float size, vec2 fragCoord) {vec2 r fragCoord / size;vec2 grid abs(fract(r - 0.5) - 0.5) / fwidth(r);float line min(grid…

Linux内核开发-编译内核源码

前言 大部分公司的所谓的Linux内核工程师主要工作是基于社区开源内核进行定制化修改&#xff0c;基本不会有机会向上游提供patch&#xff0c;仅限于公司内部业务的修修补补。 作为内核开发工程师两年多&#xff0c;精力一直被公司业务消耗&#xff0c;所有的内核知识都来自于…

异构集成封装类型2D、2.1D、2.3D、2.5D和3D封装技术

异构集成封装类型&#xff1a;2D、2.1D、2.3D、2.5D和3D封装详解 简介随着摩尔定律的放缓&#xff0c;半导体行业越来越多地采用芯片设计和异构集成封装来继续推动性能的提高。这种方法是将大型硅芯片分割成多个较小的芯片&#xff0c;分别进行设计、制造和优化&#xff0c;然后…

【深度学习驱动流体力学】计算流体力学openfoam-paraview与python3交互

目的1:配置 ParaView 中的 Python Shell 和 Python 交互环境 ParaView 提供了强大的 Python 接口,允许用户通过 Python 脚本来控制和操作其可视化功能。在 ParaView 中,可以通过 View > Python Shell 菜单打开 Python Shell 窗口,用于执行 Python 代码。要确保正确配置 …

[Linux] vi编辑器

命令模式&文本模式 命令模式就输入命令然后执行&#xff0c;文本模式就是系统把你的输入都当成写进文件里的字符 切换模式&#xff1a; 刚进入默认是命令模式&#xff0c;按: i I a A o O 进入文本模式&#xff0c; 通过他们进入文本模式有什么不同&#xff1f; 然后按esc进…

python 版本切换,更换当前默认版本

电脑可以安装多个版本&#xff0c;但是好像没有正规的维护python版本的工具&#xff0c;比如前端就有nvm切换node版本&#xff0c;但是python我没找到比较好的&#xff08;有大佬知道路过方便留言一下&#xff0c;跪谢。。&#xff09; 废话不多说&#xff0c;更改默认版本很简…

DIVE INTO DEEP LEARNING 36-49

文章目录 36. Data augmentation36.1 Training with enhanced data36.2 Enhancement measures36.3 Data augmentation summary 37. Fine tuning37.1 Fine tuning Introduce37.2 Fine tuning Step37.3 Fine tuning summary 38. Object detection38.1 Object detection38.2 Edge …

[Linux] Shell

chsh不是一种sh,而是一个命令行使用程序&#xff0c;用于更改默认shell CentOS是个开源软件&#xff0c;没有sh,sh是商业版的&#xff0c; 按ls /bin/*sh显示的sh实际上是个链接文件&#xff0c;连接的bash 在命令行输入新的sh名&#xff0c;会启动一个新的进程&#xff0c; 输…

厂里资讯之app端文章搜索

app端文章搜索 1) 内容介绍 文章搜索 ElasticSearch环境搭建 索引库创建 文章搜索多条件复合查询 索引数据同步 搜索历史记录 Mongodb环境搭建 异步保存搜索历史 查看搜索历史列表 删除搜索历史 联想词查询 联想词的来源 联想词功能实现 2) 搭建ElasticSearch环境 …

MyBatis系列七: 一级缓存,二级缓存,EnCache缓存

缓存-提高检索效率的利器 官方文档 一级缓存基本介绍快速入门Debug一级缓存执行流程一级缓存失效分析 二级缓存基本介绍快速入门Debug二级缓存执行流程注意事项和使用细节 mybatis的一级缓存和二级缓存执行顺序小实验细节说明 EnCache缓存基本介绍配置和使用EhCache细节说明 My…

SpringBoot整合Minio(支持公有及私有bucket)

&#x1f60a; 作者&#xff1a; 一恍过去 &#x1f496; 主页&#xff1a; https://blog.csdn.net/zhuocailing3390 &#x1f38a; 社区&#xff1a; Java技术栈交流 &#x1f389; 主题&#xff1a; SpringBoot整合Minio(支持公有及私有bucket) ⏱️ 创作时间&#xff1…

张大哥笔记:如何选择一个人就值得做的副业

很多人喜欢把上班称为主业&#xff0c;把上班之外的工作称为副业&#xff0c;不管以哪种方式称呼都可以&#xff0c;只要能赚钱就行&#xff0c;上班的本质就是出卖时间&#xff0c;不管你是月入5000还是月入2万&#xff0c;都是给老板打工&#xff01; 但搞笑的就是月入2万的人…

关于app爬虫的环境准备

摘要 有些数据需要在手机应用中才能查看&#xff0c;没有网页版&#xff0c;所以学习移动端的爬虫是有必要的。 手机系统分为安卓和苹果两大系统&#xff0c;本次讲解主要以安卓手机为例 有安卓手机的可以使用手机&#xff0c;没有的可以使用模拟器&#xff0c;本次以夜神模…

基于C++、MFC和Windows套接字实现的简单聊天室程序开发

一、一个简单的聊天室程序 该程序由服务器端和客户端两个项目组成&#xff0c;这两个项目均基于对话框的程序。服务器端项目负责管理客户端的上线、离线状态&#xff0c;以及转发客户端发送的信息。客户端项目则负责向服务器发送信息&#xff0c;并接收来自服务器的信息&#…

[机器学习算法]决策树

1. 理解决策树的基本概念 决策树是一种监督学习算法&#xff0c;可以用于分类和回归任务。决策树通过一系列规则将数据划分为不同的类别或值。树的每个节点表示一个特征&#xff0c;节点之间的分支表示特征的可能取值&#xff0c;叶节点表示分类或回归结果。 2. 决策树的构建…

《STM32 HAL库》小米微电机控制例程——通信协议分析及驱动库

之前有段时间因为机器狗项目的缘故&#xff0c;一直在使用小米微电机&#xff0c;但是苦于没有一个详尽的奶妈级教程&#xff0c;在控制电机的学习中踩了不少的坑。今天咱们就从头至尾一步一步的实现使用按键控制小米微电机。本文将会分析小米电机驱动库&#xff0c;并简要介绍…

练手代码之使用Python实现合并PDF文件

如果你有合并PDF的需要&#xff0c;你会怎么办 我们无所不能的程序员会选择写一个Python代码来实现&#xff08;谁会这么无聊&#xff1f;是我&#xff09;&#xff0c;如果真的有PDF操作需要&#xff0c;我推荐你使用PDF Expert这个软件哈~ 话不多说直接上代码&#xff1a; …