代码随想录算法训练营第三十天| 332.重新安排行程, 51. N皇后, 37. 解数独,总结

题目与题解

参考资料:回溯总结

332.重新安排行程

题目链接:332.重新安排行程

代码随想录题解:332.重新安排行程

视频讲解:带你学透回溯算法(理论篇)| 回溯法精讲!_哔哩哔哩_bilibili

解题思路:

        这题有两个难点,一个是要求返回的结果是按升序排列最小的,另一个是行程要保证使用每一张机票,并且假设机票行程存在环路,不能困在环中。

        针对第一个难点,可以提前对tickets进行排序,利用list.sort方法重写其中的comparator,排序的key为tickets里面每一张ticket的目的地,也就是tickets.get(i).get(1),这样保证有结果时,第一个结果一定是升序最小。

        针对第二个难点,这里是树枝的去重问题,所以可以用一个usedTickets数组,记录每一张ticket的使用情况,用过就设置为true,保证不会重复使用。

        然后就可以用回溯三部曲:

        参数有 - 用于存放结果的result,用于记录路线的path,输入tickets,usedTickets数组和每次递归时的起点start(这里也可以不需要这个参数,用path.getLast()代替)

        终止条件 - 题目要求每张机票都使用,那么每有N张机票,途径地点就有N+1个,所以当path的元素到达n+1后,路径就完成了,可以返回结果。

        单层遍历逻辑:循环遍历tickets里面的每一个元素,如果usedTickets[i]为true,或者tickets.get(i).get(1) 不等于start,则跳过该循环;否则将tickets.get(i).get(1)加入path,usedTickets[i]设置为true,调用回溯方法,修改start为tickets.get(i).get(1),出来后修改usedTickets[i]为false并弹出path最后一个元素即可。

class Solution {
	List<String> result = new ArrayList<>();
	LinkedList<String> path = new LinkedList<>();
    public List<String> findItinerary(List<List<String>> tickets) {
		boolean[] usedTickets = new boolean[tickets.size()];
		// tickets.sort((list1, list2) -> list1.get(0).compareTo(list2.get(0)));
		tickets.sort(Comparator.comparing(list -> list.get(1)));
		path.add("JFK");
		findItinerary(tickets, usedTickets, "JFK");
		return result;
    }

	boolean findItinerary(List<List<String>> tickets, boolean[] usedTickets, String start) {
		if (path.size() == tickets.size() + 1) {
			result = new ArrayList<>(path);
			return true;
		}
		for (int i = 0; i < tickets.size(); i++) {
			if (usedTickets[i] || !tickets.get(i).get(0).equals(start)) continue;
			path.add(tickets.get(i).get(1));
			usedTickets[i] = true;
			if (findItinerary(tickets, usedTickets, tickets.get(i).get(1)))
				return true;
			usedTickets[i] = false;
			path.pollLast();
		}
		return false;
	}
}

但是这样写在leetcode上不能ac,会提示超时,因为每次遍历tickets都是从头开始遍历的,搜索效率非常低,需要用map替代list。 

看完代码随想录之后的想法 

        随想录答案改造了一下ticket,用Map<String, Map<String, Integer>> map存储tickets每一个起点对应的多个目的地,以及机票用过与否的情况。目前自己写还比较难,先放着以后看。

class Solution {
    private Deque<String> res;
    private Map<String, Map<String, Integer>> map;

    private boolean backTracking(int ticketNum){
        if(res.size() == ticketNum + 1){
            return true;
        }
        String last = res.getLast();
        if(map.containsKey(last)){//防止出现null
            for(Map.Entry<String, Integer> target : map.get(last).entrySet()){
                int count = target.getValue();
                if(count > 0){
                    res.add(target.getKey());
                    target.setValue(count - 1);
                    if(backTracking(ticketNum)) return true;
                    res.removeLast();
                    target.setValue(count);
                }
            }
        }
        return false;
    }

    public List<String> findItinerary(List<List<String>> tickets) {
        map = new HashMap<String, Map<String, Integer>>();
        res = new LinkedList<>();
        for(List<String> t : tickets){
            Map<String, Integer> temp;
            if(map.containsKey(t.get(0))){
                temp = map.get(t.get(0));
                temp.put(t.get(1), temp.getOrDefault(t.get(1), 0) + 1);
            }else{
                temp = new TreeMap<>();//升序Map
                temp.put(t.get(1), 1);
            }
            map.put(t.get(0), temp);

        }
        res.add("JFK");
        backTracking(tickets.size());
        return new ArrayList<>(res);
    }
}

遇到的困难

        想了一个多小时,超时问题实在不知道怎么解,hard不愧是hard。

51. N皇后

题目链接:51. N皇后

代码随想录题解:51. N皇后

视频讲解:​​​​​​​这就是传说中的N皇后? 回溯算法安排!| LeetCode:51.N皇后_哔哩哔哩_bilibili

解题思路:

       两眼一麻黑,直接抄答案。

看完代码随想录之后的想法 

        重点还是得把图画出来,理清每一层的思路,才能真正写出来。

        首先来看一下皇后们的约束条件:

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

确定完约束条件,来看看究竟要怎么去搜索皇后们的位置,这里可以抽象为一棵树。

用一个 3 * 3 的棋盘,将搜索过程抽象为一棵树,如图:

51.N皇后

从图中,可以看出,二维矩阵中矩阵的高就是这棵树的高度,矩阵的宽就是树形结构中每一个节点的宽度。

那么我们用皇后们的约束条件,来回溯搜索这棵树,只要搜索到了树的叶子节点,说明就找到了皇后们的合理位置了

递归函数参数:定义全局变量二维数组result来记录最终结果,参数n是棋盘的大小,然后用row来记录当前遍历到棋盘的第几层了。

终止条件:当递归到棋盘最底层(也就是叶子节点)的时候,就可以收集结果并返回了,此时row=n

单层搜索的逻辑:递归深度就是row控制棋盘的行,每一层里for循环的col控制棋盘的列,一行一列,确定了放置皇后的位置。每次都是要从新的一行的起始位置开始搜,所以都是从0开始。

验证棋盘是否合法:按照如下标准去重:

  1. 不能同行,这里不需要检查,因为每次递归必然是换新的一行
  2. 不能同列
  3. 不能同斜线 (45度和135度角),这里注意超过180度的对角不用考虑,因为按递归的顺序,大于row的行里面不会有棋子。
class Solution {
	List<List<String>> result = new ArrayList<>();
	List<String> path = new ArrayList<>();
    public List<List<String>> solveNQueens(int n) {
		char[][] chessboard = new char[n][n];
		for (int i = 0; i < n; i++) {
			Arrays.fill(chessboard[i], '.');
		}
		solveNQueens(n, 0, chessboard);
		return result;
    }
	void solveNQueens(int n, int row, char[][] chessboard) {
		if (row == n) {
			List<String> temp= new ArrayList<>();
			for (int i = 0; i < n; i++) {
				temp.add(String.copyValueOf(chessboard[i]));
			}
			result.add(temp);
			return;
		}
		for (int i = 0; i < n; i++) {
			if (!isValid(chessboard, i, row, n)) continue;
			chessboard[row][i] = 'Q';
			solveNQueens(n, row+1, chessboard);
			chessboard[row][i] = '.';
		}
	}

	boolean isValid(char[][] chessboard, int col, int row, int n) {
		for (int i = 0; i < n; i++) {
			if (chessboard[i][col] == 'Q')
				return false;
		}
		for (int i = 1; col - i >= 0 && row - i >= 0 ; i++) {
			if (chessboard[row - i][col - i] == 'Q')
				return false;
		}
		for (int i = 1; col + i < n && row - i >= 0 ; i++) {
			if (chessboard[row - i][col + i] == 'Q')
				return false;
		}
		return true;
	}
}

遇到的困难

        一开始连N皇后问题的定义都不是很清楚,就抓瞎了,这种特型的二维数组题以后就有参考标准了。

37. 解数独

题目链接:37. 解数独

代码随想录题解:​​​​​​​​​​​​​​37. 解数独

视频讲解:回溯算法二维递归?解数独不过如此!| LeetCode:37. 解数独_哔哩哔哩_bilibili

解题思路:

       见答案,二刷再看

看完代码随想录之后的想法 

        

遇到的困难

        

今日收获

        今天全是hard题,确实很难,二刷再好好看。

回溯总结:

回溯算法能解决如下问题:

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

在树形结构中子集问题是要收集所有节点的结果,而组合问题是收集叶子节点的结果。

对于组合问题,for循环在寻找起点的时候要有一个范围,如果这个起点到集合终止之间的元素已经不够题目要求的k个元素了,就没有必要搜索了

排列问题与组合的不同:

  • 每层都是从0开始搜索而不是startIndex
  • 需要used数组记录path里都放了哪些元素了

去重:使用set去重的版本相对于used数组的版本效率都要低很多

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【随笔】Git 高级篇 -- 相对引用2(十三)

&#x1f48c; 所属专栏&#xff1a;【Git】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &#x1f496; 欢迎大…

每日一题(leetcode287):寻找重复数--二分查找+思维

思路&#xff1a;看官方解答 class Solution { public:int findDuplicate(vector<int>& nums) {int nnums.size();int left1;int rightn-1;int ans-1;while(left<right){int mid(leftright)/2;int count0;for(int j0;j<n;j){if(nums[j]<mid){count;}}if(co…

小林coding图解计算机网络|基础篇03|Linux 系统是如何收发网络包的?

小林coding网站通道&#xff1a;入口 本篇文章摘抄应付面试的重点内容&#xff0c;详细内容还请移步&#xff1a;小林coding网站通道 文章目录 网络模型Linux 网络协议栈Linux 接收网络包的流程Linux发送网络包的流程为什么全部数据包只用一个结构体来描述呢发送网络数据的时候…

[HackMyVM]靶场Logan2

难度:Medium kali:192.168.56.104 靶机:192.168.56.146 端口扫描 ┌──(root㉿kali2)-[~/Desktop] └─# nmap 192.168.56.146 Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-04-04 19:41 CST Nmap scan report for 192.168.56.146 Host is up (0.000067s latency)…

0201基础集成与使用-微信支付-支付模块-项目实战

文章目录 一、前言二、springboot集成2.1 配置信息与配置类2.2 微信相关枚举信息2.3 工具类2.4 业务接口 三、演示-支付与退款结语 一、前言 下面我以微信支付v3为例&#xff0c;通过spirngboot集成到我们的项目中&#xff0c;不依赖其他第三方框架。当然适用简单项目&#xf…

软考--软件设计师(软件工程总结2)

目录 1.测试方法 2.软件项目管理 3.软件容错技术 4.软件复杂性度量 5.结构化分析方法&#xff08;一种面向数据流的开发方法&#xff09; 6.数据流图 1.测试方法 软件测试&#xff1a;静态测试&#xff08;被测程序采用人工检测&#xff0c;计算机辅助静态分析的手段&…

Unity开发之音效相关

目录 音频文件的导入 音频源相关 麦克风输入相关 获取麦克风设备信息 开始录制 获取音频数据用于存储或者传输 代码控制音频源 动态控制音效播放 示例 音频文件的导入 常用格式&#xff1a;wav,mp3,ogg,aiff Force To Mono(多声道转单声道)Normalize(强制为单声道&am…

C++入门 (2) >>引用>>内联函数>>auto关键字

1 引用 定义&#xff1a;给变量起别名。 方法&#xff1a;在类型后面加上&符号。 主要作用&#xff1a;代替函数传指针。 例&#xff1a; void test(int& a) //参数为int&类型 {a 10; }int main() {int m 3;int& z m; //给m起别名叫z&#xff0…

基于springboot+vue+Mysql的在线考试系统

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…

MySQL8,体验不一样的安装方式!

MySQL官网中下载YUM源rpm安装包。 1、把上面的rpm文件下载下来放到服务器上 #或者在linux系统中通过wget命令下载 wget http://dev.mysql.com/get/mysql80-community-release-el7-1.noarch.rpm2、下载完成后使用yum命令本地安装yum源 yum localinstall mysql80-community-rel…

Linux云计算之Linux基础3——Linux基本认识操作

1、终端 终端(terminal)&#xff1a;人和系统交互的必要设备&#xff0c;人机交互最后一个界面&#xff08;包含独立的输入输出设备&#xff09; 物理终端(console)&#xff1a;直接接入本机器的键盘设备和显示器虚拟终端(tty)&#xff1a;通过软件方式虚拟实现的终端。它可以…

IP-guard WebServer 任意文件读取漏洞复现

0x01 产品简介 IP-guard是由溢信科技股份有限公司开发的一款终端安全管理软件,旨在帮助企业保护终端设备安全、数据安全、管理网络使用和简化IT系统管理。 0x02 漏洞概述 由于IP-guard WebServer /ipg/static/appr/lib/flexpaper/php/view.php接口处未对用户输入的数据进行严…

VMamba: Visual State Space Model

VMamba: Visual State Space Model VMamba&#xff1a;视觉状态空间模型 论文链接&#xff1a;http://arxiv.org/abs/2401.10166 代码链接&#xff1a;https://github.com/MzeroMiko/VMamba 1、摘要 借鉴了最近引入的状态空间模型SSM&#xff0c;提出了Visual State Space M…

如何保证Redis的缓存和数据库中的数据的一致性?

Redis的缓存如何和数据库中的数据保持一致性&#xff1f; 我们都知道&#xff0c;Redis是一个基于内存的键值存储系统&#xff0c;数据完全存放在内存中&#xff0c;这使得它的读写速度远超传统的硬盘存储数据库。对于高访问频率、低修改率的数据&#xff0c;通过将它们缓存在…

动态规划:线性dp

1.最长公共子序列(LCS) dp[i][j]含义&#xff1a;序列Ai(a1-ai)和Bj(b1-bj)的最长公共子序列长度 分析两种情况&#xff1a; &#xff08;1&#xff09;当ai bj时&#xff0c;已经求得Ai-1和Bj-1的最长公共子序列 dp[i][j] dp[i-1][j-1] 1 &#xff08;2&#xff09;当…

C++:比较运算符(18)

就是进行数据的比较&#xff0c;表达式正确的话就是真&#xff0c;错的话就是假&#xff0c;真假则由bool值来代替&#xff0c;非0即真 等于&#xff08;为赋值&#xff0c;为比较&#xff09;10 200!不等于10 ! 201>大于10 > 200<小于10 < 201>大于等于20 >…

windows安装Openssl

openssl官网:[ Downloads ] - /source/index.html Windows 安装方法 OpenSSL 官网没有提供 Windows 版本的安装包&#xff0c;可以选择其他开源平台提供的工具 Win32/Win64 OpenSSL Installer for Windows - Shining Light Productions 等待下载完成 捐不起 配置环境变量 ope…

【图论】【基环内向树】【广度优先】【深度优先】2127. 参加会议的最多员工数

作者推荐 视频算法专题 本文涉及知识点 图论 基环内向树 LeetCode2127. 参加会议的最多员工数 一个公司准备组织一场会议&#xff0c;邀请名单上有 n 位员工。公司准备了一张 圆形 的桌子&#xff0c;可以坐下 任意数目 的员工。 员工编号为 0 到 n - 1 。每位员工都有一位…

XML --java学习笔记

XML(全称EXtensible Markup Language&#xff0c;可扩展标记语言) 本质是一种数据的格式&#xff0c;可以用来存储复杂的数据结构&#xff0c;和数据关系 XML的特点 XML中的“<标签名>”称为一个标签或一个元素&#xff0c;一般是成对出现的XML中的标签名可以自己定义…

数字信号处理实验---FFT分析

一、题目&#xff1a; 二、实验要求&#xff1a; 1、绘制图形时&#xff0c;尽量选用已经提供的函数。 2、所有的图形&#xff0c;需要加上横坐标、纵坐标以及标题的说明。 3、将设计的程序保存为脚本文件&#xff0c;在实验报告中&#xff0c;需写出程序语句。 4、Matlab程…