训练营第二十七天 | 491.递增子序列46.全排列47.全排列 II332.重新安排行程51. N皇后

491.递增子序列

力扣题目链接(opens new window)

给定一个整型数组, 你的任务是找到所有该数组的递增子序列,递增子序列的长度至少是2。

示例:

  • 输入: [4, 6, 7, 7]
  • 输出: [[4, 6], [4, 7], [4, 6, 7], [4, 6, 7, 7], [6, 7], [6, 7, 7], [7,7], [4,7,7]]

说明:

  • 给定数组的长度不会超过15。
  • 数组中的整数范围是 [-100,100]。
  • 给定数组中可能包含重复数字,相等的数字应该被视为递增的一种情况。

思路:

class Solution {
private:vector<vector<int>> result;vector<int> path;void backtracking(vector<int>& nums, int startindex) {if (path.size() > 1) result.push_back(path);for (int i = startindex; i < nums.size(); i++) {if (i > startindex && nums[i] == nums[i - 1]) continue;  // 跳过重复元素if (path.empty() || nums[i] >= path.back()) {  // 确保递增顺序path.push_back(nums[i]);backtracking(nums, i + 1);path.pop_back();}}}
public:vector<vector<int>> findSubsequences(vector<int>& nums) {result.clear();path.clear();backtracking(nums, 0);return result;}
};

初始代码:

没有正确处理重复元素的情况。如果输入数组中有重复元素,直接跳过重复的元素,这样会遗漏一些合法的递增子序列。

为了正确处理重复元素,需要在每一层递归中使用一个集合(如 unordered_set)来记录当前层中已经使用过的元素,以确保每个元素在每一层递归中只使用一次,但在不同的递归路径中可以使用相同的元素。

unordered_set<int> used;  // 使用集合来记录当前层使用过的元素

if (used.find(nums[i]) != used.end()) continue;  // 当前层已经使用过的元素跳过

if (path.empty() || nums[i] >= path.back()) {  // 确保递增顺序

改正后的代码:

class Solution {
private:vector<vector<int>> result;vector<int> path;void backtracking(vector<int>& nums, int startindex) {if (path.size() > 1) result.push_back(path);unordered_set<int> used;  // 使用集合来记录当前层使用过的元素for (int i = startindex; i < nums.size(); i++) {if (used.find(nums[i]) != used.end()) continue;  // 当前层已经使用过的元素跳过if (path.empty() || nums[i] >= path.back()) {  // 确保递增顺序used.insert(nums[i]);  // 记录当前元素path.push_back(nums[i]);backtracking(nums, i + 1);path.pop_back();}}}
public:vector<vector<int>> findSubsequences(vector<int>& nums) {result.clear();path.clear();backtracking(nums, 0);return result;}
};

46.全排列

力扣题目链接(opens new window)

给定一个 没有重复 数字的序列,返回其所有可能的全排列。

示例:

  • 输入: [1,2,3]
  • 输出: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] ]

思路:

该题在回溯法的基础上加了一个used数组,存储数组对应元素是否使用过,以此作为条件判断是否将该数加入path。

            if (used[i]) continue;used[i] = true;path.push_back(nums[i]);backtrack(nums, used);path.pop_back();used[i] = false;

同时,该题不需要startindex,因为每次循环都是将未加入path的所有元素依次遍历加入path。而是用used代替了,作为参数值传入backtrack函数。

class Solution {
private:vector<vector<int>> result;vector<int> path; // 全局变量void backtrack(vector<int>& nums, vector<bool>& used) {if (path.size() == nums.size()) {result.push_back(path);return;}for (int i = 0; i < nums.size(); i++) {if (used[i]) continue;used[i] = true;path.push_back(nums[i]);backtrack(nums, used);path.pop_back();used[i] = false;}}public:vector<vector<int>> permute(vector<int>& nums) {result.clear();path.clear();vector<bool> used(nums.size(), false);backtrack(nums, used);return result;}
};

47.全排列 II

力扣题目链接(opens new window)

给定一个可包含重复数字的序列 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

思路:

该题就多了一个去重操作。先给数组排序,然后还是使用used的方式递归。

其中特别注意:if (i > 0 && nums[i] == nums[i - 1]&& !used[i - 1]) continue;中不要忘记“!used[i - 1]”。!used[i - 1]:确保在当前层级中,前一个相同元素没有被使用。如果前一个相同元素没有被使用,则跳过当前元素。这一步的目的是避免在同一层级中选择相同的元素,从而防止生成重复的排列。如果used[i - 1] == true。则同一树枝重复,是被允许的。

class Solution {private:vector<vector<int>> result;vector<int> path;void backtrack(vector<int>& nums, vector<bool>& used) {if (path.size() == nums.size()) {result.push_back(path);return;}for (int i = 0; i < nums.size(); i++){if (used[i]) continue;           if (i > 0 && nums[i] == nums[i - 1]&& !used[i - 1]) continue;used[i] = true;path.push_back(nums[i]);backtrack(nums, used);path.pop_back();used[i] = false;}}
public:vector<vector<int>> permuteUnique(vector<int>& nums) {vector<bool> used(nums.size(), false);sort(nums.begin(), nums.end());backtrack(nums, used);return result;}
};

332.重新安排行程

力扣题目链接(opens new window)

给定一个机票的字符串二维数组 [from, to],子数组中的两个成员分别表示飞机出发和降落的机场地点,对该行程进行重新规划排序。所有这些机票都属于一个从 JFK(肯尼迪国际机场)出发的先生,所以该行程必须从 JFK 开始。

提示:

  • 如果存在多种有效的行程,请你按字符自然排序返回最小的行程组合。例如,行程 ["JFK", "LGA"] 与 ["JFK", "LGB"] 相比就更小,排序更靠前
  • 所有的机场都用三个大写字母表示(机场代码)。
  • 假定所有机票至少存在一种合理的行程。
  • 所有的机票必须都用一次 且 只能用一次。

示例 1:

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

示例 2:

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

思路: 

使用unordered_map<string, map<string, int>> targets; 来记录航班的映射关系,定义为全局变量。参数里还需要ticketNum,表示有多少个航班(终止条件会用上)。

代码如下:

// unordered_map<出发机场, map<到达机场, 航班次数>> targets
unordered_map<string, map<string, int>> targets;
bool backtracking(int ticketNum, vector<string>& result) {

返回值用bool!

因为只需要找到一个行程,就是在树形结构中唯一的一条通向叶子节点的路线,所以找到了这个叶子节点了直接返回。

  • 递归终止条件

拿题目中的示例为例,输入: [["MUC", "LHR"], ["JFK", "MUC"], ["SFO", "SJC"], ["LHR", "SFO"]] ,这是有4个航班,那么只要找出一种行程,行程里的机场个数是5就可以了。

所以终止条件是:回溯遍历的过程中,遇到的机场个数,如果达到了(航班数量+1),那么我们就找到了一个行程,把所有航班串在一起了。

  • 单层搜索的逻辑

在选择映射函数的时候,不能选择unordered_map<string, multiset<string>> targets, 因为一旦有元素增删multiset的迭代器就会失效。

可以说本题既要找到一个对数据进行排序的容器,而且还要容易增删元素,迭代器还不能失效

所以我选择了unordered_map<string, map<string, int>> targets 来做机场之间的映射。

class Solution {
private:
// unordered_map<出发机场, map<到达机场, 航班次数>> targets
unordered_map<string, map<string, int>> targets;
bool backtracking(int ticketNum, vector<string>& result) {if (result.size() == ticketNum + 1) {return true;}for (pair<const string, int>& target : targets[result[result.size() - 1]]) {if (target.second > 0 ) { // 记录到达机场是否飞过了result.push_back(target.first);target.second--;if (backtracking(ticketNum, result)) return true;result.pop_back();target.second++;}}return false;
}
public:vector<string> findItinerary(vector<vector<string>>& tickets) {targets.clear();vector<string> result;for (const vector<string>& vec : tickets) {targets[vec[0]][vec[1]]++; // 记录映射关系}result.push_back("JFK"); // 起始机场backtracking(tickets.size(), result);return result;}
};

51. N皇后

力扣题目链接(opens new window)

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

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

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

示例 1:

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

示例 2:

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

class Solution {
private:vector<vector<string>> result;void backtrack(int n, int i, vector<vector<char>>& chessboard, vector<bool>& used) {if (i == n) {vector<string> board;for (const auto& row : chessboard) {board.push_back(string(row.begin(), row.end()));}result.push_back(board);return;}for (int j = 0; j < n; j++) {if (used[j] || !valid(i, j, chessboard, n)) continue;chessboard[i][j] = 'Q'; // 放置皇后used[j] = true;backtrack(n, i + 1, chessboard, used);chessboard[i][j] = '.'; // 回溯,撤销皇后used[j] = false;}}bool valid(int i, int j, vector<vector<char>>& chessboard, int n) {// 检查左上对角线for (int k = i - 1, h = j - 1; k >= 0 && h >= 0; k--, h--) {if (chessboard[k][h] == 'Q') return false;}// 检查右上对角线for (int k = i - 1, h = j + 1; k >= 0 && h < n; k--, h++) {if (chessboard[k][h] == 'Q') return false;}return true;}public:vector<vector<string>> solveNQueens(int n) {vector<vector<char>> chessboard(n, vector<char>(n, '.'));vector<bool> used(n, false);backtrack(n, 0, chessboard, used);return result;}
};

37. 解数独

力扣题目链接(opens new window)

编写一个程序,通过填充空格来解决数独问题。

一个数独的解法需遵循如下规则: 数字 1-9 在每一行只能出现一次。 数字 1-9 在每一列只能出现一次。 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。 空白格用 '.' 表示。

解数独

一个数独。

解数独

答案被标成红色。

提示:

  • 给定的数独序列只包含数字 1-9 和字符 '.' 。
  • 你可以假设给定的数独只有唯一解。
  • 给定数独永远是 9x9 形式的。

思路:

树枝是board的每一个空格,用双层for循环(行、列)遍历,如果等于‘.‘ , 则填入数字。树层是每个空格可以填入的数字,可以设置一个辅助函数判断该数字是否符合要求, 若符合则继续填入下一个空格。其中特别注意,这个回溯函数是一个bool函数,因为解数独找到一个符合的条件(就在树的叶子节点上)立刻就返回,相当于找从根节点到叶子节点一条唯一路径,所以需要使用bool返回值。

找九宫格的时候,可以通过int startRow = (row / 3) * 3;找到特定位置。

class Solution {
private:bool backtrack(vector<vector<char>>& board) {for (int i = 0; i < 9; i++) {for (int j = 0; j < 9; j++) {if (board[i][j] == '.') {for (char n = '1'; n <= '9'; n++) {if (valid(i, j, n, board)) {board[i][j] = n;if (backtrack(board)) {return true;}board[i][j] = '.';}}return false;}}}return true;}bool valid(int row, int col, char val, vector<vector<char>>& board) {for (int i = 0; i < 9; i++) {if (board[row][i] == val) {return false;}}for (int j = 0; j < 9; j++) {if (board[j][col] == val) {return false;}}int startRow = (row / 3) * 3;int startCol = (col / 3) * 3;for (int i = startRow; i < startRow + 3; i++) {for (int j = startCol; j < startCol + 3; j++) {if (board[i][j] == val) {return false;}}}return true;}public:void solveSudoku(vector<vector<char>>& board) {backtrack(board);}
};

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

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

相关文章

Python脚本自动填充数据和生成文档轻松办公

一&#xff0c;自动填充数据生成word文档 代码&#xff1a; from docx import Document# 创建一个新的Word文档对象 doc Document()# 添加标题 doc.add_heading(自动填充数据和生成文档, level1)# 添加段落 doc.add_paragraph(这是一个使用Python脚本自动填充数据并生成文档的…

刷新方盒子最快10万销量纪录 捷途旅行者何以颠覆越野市场?

近年”方盒子“产品迅速崛起&#xff0c;在新一轮的市场角逐中&#xff0c;率先突围的并非传统豪强&#xff0c;而是首次进军越野市场的捷途汽车。作为“燃油车&#xff0c;”捷途旅行者&#xff0c;在面对纯电、混动等产品的强势围剿下&#xff0c;仅用时9个月便成为细分市场销…

基于细节增强卷积和内容引导注意的单图像去雾

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 摘要Abstract文献阅读&#xff1a;DEA-Net&#xff1a;基于细节增强卷积和内容引导注意的单图像去雾1、研究背景2、方法提出3、相关知识3.1、DEConv3.3、多重卷积的…

C语言指针与数组名的联系

目录 一、数组名的理解 a.数组名代表数组首元素的地址 b. 两个例外 二、使用指针来访问数组 三、一维数组传参的本质 一、数组名的理解 a.数组名代表数组首元素的地址 我们在使用指针访问数组的内容时&#xff0c;有这样的代码&#xff1a; int arr[10] {1,2,3,4,5,6,7,…

枚举(enum)+联合体(union)

枚举联合 一.枚举类型1.枚举类型的声明2.枚举类型的优点3.枚举类型的使用 二.联合体1.联合体类型的声明2.联合体的特点3.相同成员的结构体和联合体对比4.联合体大小的计算5.联合体的练习&#xff08;判断大小端&#xff09;6.联合体节省空间例题 一.枚举类型 1.枚举类型的声明…

Sentinel1.8.6更改配置同步到nacos(项目是Gateway)

本次修改的源码在&#xff1a;https://gitee.com/stonic-open-source/sentinel-parent 一 下载源码 地址&#xff1a;https://github.com/alibaba/Sentinel/releases/tag/1.8.6 二 导入idea&#xff0c;等待maven下载好各种依赖 三 打开sentile-dashboard这个模块&#xf…

华为手机录屏在哪里?图文详解帮你找!

随着科技的进步&#xff0c;智能手机已成为我们日常生活中不可或缺的工具。其中&#xff0c;华为手机凭借其卓越的性能和用户体验&#xff0c;在全球范围内赢得了广泛的赞誉。在众多功能中&#xff0c;录屏功能尤为实用&#xff0c;无论是制作教程、记录游戏精彩瞬间&#xff0…

压敏电阻器是在规定温度下,当电压超过某一临界值时电导随电压的升高而急速增大的一种电阻器

压敏电阻器是在规定温度下,当电压超过某一临界值时电导随电压的升高而急速增大的一种电阻器。压敏电阻器的伏安特性是非线性的,因此,压敏电阻器亦称为非线性电阻器,非线性来自于压敏电阻器两端的外加电压,其伏安特性如图 9-1所示。从图9-1可以看出,压敏电阻器有对称型和非对称型…

网络运维简介

目录 1.网络运维的定义 2.诞生背景 3.网络运维的重要性 4.优点 5.缺点 6.应用场景 6.1.十个应用场景 6.2.数据中心运维 7.应用实例 8.小结 1.网络运维的定义 网络运维&#xff08;Network Operations&#xff09;是指管理、监控和维护计算机网络以确保其高效、安全和…

Python私教张大鹏 Vue3整合AntDesignVue之文本组件

案例&#xff1a;展示标题 核心代码&#xff1a; <a-typography><a-typography-title>Introduction</a-typography-title> </a-typography>vue3示例&#xff1a; <template><a-typography><a-typography-title>这是一个标题</…

【K8s】专题四(6):Kubernetes 控制器之 Job

以下内容均来自个人笔记并重新梳理&#xff0c;如有错误欢迎指正&#xff01;如果对您有帮助&#xff0c;烦请点赞、关注、转发&#xff01;欢迎扫码关注个人公众号&#xff01; 目录 一、基本介绍 二、工作原理 三、相关特性 四、资源清单&#xff08;示例&#xff09; 五…

电路分析答疑 1

三要素法求解的时候&#xff0c; 电容先求U&#xff0c;再利用求导求I 电感先求I&#xff0c;再利用求导求U 若I的头上没有点点&#xff0c;那就是求有效值 叠加定理&#xff0c;不要忘记 若电流值或者电压值已经给出来了&#xff0c;那就说明这一定是直流电。 在画画圈的时候…

数据库(25)——多表关系介绍

在项目开发中&#xff0c;进行数据库表结构设计时&#xff0c;会根据业务需求及业务模块之间的关系&#xff0c;分析并设计表结构&#xff0c;各个表之间的结构基本上分为三种&#xff1a;一对多&#xff0c;多对多&#xff0c;一对一。 一对多 例如&#xff0c;一个学校可以有…

Mac修改Mysql8.0密码

转载请标明出处&#xff1a;http://blog.csdn.net/donkor_/article/details/139392605 文章目录 前言修改密码Step1:修改my.conf文件Step2:添加配置skip-grant-tablesStep3:重启mysql服务Step4:进入mysqlStep5:刷新权限Step6:修改密码Step7:再次刷新权限Step8:删除/注释 skip-…

DNS域名

DNS域名 DNS是域名系统的简称 域名和ip地址之间的映射关系 互联网中&#xff0c;ip地址是通信的唯一标识 访问网站&#xff0c;域名&#xff0c;ip地址不好记&#xff0c;域名朗朗上口&#xff0c;好记。 域名解析的目的就是为了实现&#xff0c;访问域名就等于访问ip地址…

【Python】 获取当前日期的Python代码解析与应用

标题&#xff1a;Python中获取当前日期的简单指南 基本原理 在Python中&#xff0c;获取当前日期是一个常见的需求&#xff0c;尤其是在处理日志、数据记录和时间相关的任务时。Python提供了多种方式来获取和处理日期和时间&#xff0c;其中最常用的模块是datetime。datetime…

多客陪玩系统-开源陪玩系统平台源码-支持游戏线上陪玩家政线下预约等多场景应用支持H5+小程序+APP

多客陪玩系统-开源陪玩系统平台源码-支持游戏线上陪玩家政按摩线下预约等多场景应用支持H5小程序APP 软件架构 前端&#xff1a;Uniapp-vue2.0 后端&#xff1a;Thinkphp6 前后端分离 前端支持&#xff1a; H5小程序双端APP&#xff08;安卓苹果&#xff09; 安装教程 【商业…

QT C++ QTableWidget 表格合并 setSpan 简单例子

这里说的合并指的是单元格&#xff0c;不是表头。span的意思是跨度、宽度、范围。 setSpan函数需要设定行、列、行跨几格&#xff0c;列跨几格。 //函数原型如下 void QTableView::setSpan(int row, i nt column, 、 int rowSpanCount,/*行跨过的格数*/ int columnSpanCount…

【算法无用系列】电影推荐——余弦相似度计算用户相似度原理

【算法无用系列】通过余弦相似度计算电影、用户相似度 话不多说&#xff0c;本文通过电影推荐系统中&#xff0c;基于余弦相似度算法计算出用户相似和电影相似原理。希望可以帮助一些代码不懂的同学一些思路。 记录用户电影评分数据 一般情况来说&#xff0c;会根据用户的行为…

什么是数字化转型?

作者&#xff1a; 峡山老曹 数字神化 ”企业如何实现数字化转型“是摆在现代企业面前一个无法回避的问题&#xff0c;数字化转型的重要性不容忽视&#xff0c;它不仅是企业适应数字化时代的必然要求&#xff0c;更是提升竞争力、实现可持续发展的关键。随着科技的飞速发展和市场…