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

news2024/11/16 12:42:46

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.coloradmin.cn/o/1793444.html

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

相关文章

新手学习编程网站一站式合集

LTPP在线开发平台 探索编程世界的新天地&#xff0c;为学生和开发者精心打造的编程平台&#xff0c;现已盛大开启&#xff01;这个平台汇集了近4000道精心设计的编程题目&#xff0c;覆盖了C、C、JavaScript、TypeScript、Go、Rust、PHP、Java、Ruby、Python3以及C#等众多编程语…

【Java】---- SpringBoot 统一数据返回格式

目录 1. 统一数据返回格式介绍2. 实际应用2.1 添加前后的返回结果区别2.2 存在问题 3. 统一数据返回格式的优点 1. 统一数据返回格式介绍 通过使用ControllerAdvice和引用ResponseBodyAdvice接口来进行实现。 ResponseBodyAdvice这个接口里面有两个方法&#xff0c;分别是: s…

B端数据看板,其实数据可以更美的。

B端数据看板可以通过设计来提升其美观度。 色彩和配色方案&#xff1a; 选择适合品牌和数据类型的色彩搭配方案。使用渐变色、明亮的色调和对比度来突出重要的数据指标。 数据可视化&#xff1a; 使用图表、图形和数据图像来呈现数据&#xff0c;使其更易于理解和解读。选择…

【算法】合并两个有序链表(easy)——递归算法

题解&#xff1a;合并两个有序链表(easy)——递归求解 目录 1.题目2.题解3.参考代码4.总结 1.题目 题目链接&#xff1a;LINK 2.题解 本题有两种解法&#xff0c; 一是用循环去处理 链接&#xff1a;【刷题记录】合并两个有序数组、移除元素二是用递归去处理 将在下面中说…

买视觉检测设备需要多少钱?

随着工业自动化的发展&#xff0c;其应用范围逐步提高&#xff0c;其中母子图像传感器、CMOS和CCD摄像机、DSP、ARM嵌入式技术、图像处理和模式识别技术的快速发展&#xff0c;有效地推动了视觉检测设备的发展。在机器视觉领域中&#xff0c;常见的就是视觉检测、视觉识别、视觉…

统计信号处理基础 习题解答10-6

题目 在例10.1中&#xff0c;把数据模型修正为&#xff1a; 其中是WGN&#xff0c;如果&#xff0c;那么方差&#xff0c;如果&#xff0c;那么方差。求PDF 。把它与经典情况PDF 进行比较&#xff0c;在经典的情况下A是确定性的&#xff0c;是WGN&#xff0c;它的方差为&#…

蒙层(css)

如何在 Vue 中实现一个包含图像和蒙层效果的组件&#xff1f;这个组件根据某个条件显示或隐藏蒙层&#xff0c;用于表示图像是否已读。 1. 创建基础模板 首先&#xff0c;我们在模板中使用 div 包裹我们的图像组件 GraphImage&#xff0c;并为最外层 div 设置 position: relat…

WordPress plugin MStore API SQL注入漏洞复现(CVE-2023-3077)

0x01 产品简介 WordPress和WordPress plugin都是WordPress基金会的产品。WordPress是一套使用PHP语言开发的博客平台。该平台支持在PHP和MySQL的服务器上架设个人博客网站。WordPress plugin是一个应用插件。 0x02 漏洞概述 WordPress plugin MStore API 3.9.8 版本之前存在S…

【逻辑回归】Logistic Regression逻辑回归模型学习笔记

文章目录 序言1. 线性回归2. 逻辑回归2.1 引入逻辑回归的原因2.2 逻辑回归2.3 逻辑回归的应用 3. 逻辑函数3.1 sigmoid函数3.2 sigmoid函数的性质3.3 决策边界3.4 对数几率 4. 损失函数4.1 为什么说逻辑回归时概率类模型4.2 为什么要进行极大似然估计4.3 利用MLE如何推导出损失…

XML解析库tinyxml2库使用详解

XML语法规则介绍及总结-CSDN博客 TinyXML-2 是一个简单轻量级的 C XML 解析库,它提供了一种快速、高效地解析 XML 文档的方式。 1. 下载地址 Gitee 极速下载/tinyxml2 2. 基本用法 下面将详细介绍 TinyXML-2 的主要使用方法: 2.1. 引入头文件和命名空间 #i…

Linux操作系统:Redis在虚拟环境下的安装与部署

Redis下载方法 最近部署项目的时候用到了Redis&#xff0c;自己在安装的时候也碰到了一些列问题最终安装成功&#xff0c;记录一下自己的安装历程。前期准备&#xff1a; 服务器Linux版本&#xff1a;Centos8.4 64位&#xff08;http://isoredirect.centos.org/centos/8/isos/…

Django 部署指南

部署 Django 应用程序涉及将我们的应用程序从开发环境部署到生产环境&#xff0c;并确保它可以在生产服务器上安全运行和扩展。其实了解几种部署方案&#xff0c;相信你对将来的项目更得心应手。 1、问题背景 Django 是一款流行的 Python Web 框架&#xff0c;但对于新手来说&…

Parallels Desktop 优化大学 IT 环境的八大最佳实践

在不断变化的大学 IT 环境中&#xff0c;优化资源和确保无缝运营至关重要。Parallels Desktop 是学术用户弥合 Mac 和 Windows 环境之间差距的强大工具。 大学 IT 部门可以在很多方面受益于 Parallels Desktop&#xff0c;主要原因是它使 IT 管理员能够提供让 Mac 用户无缝运行…

Aigtek功率放大器由什么组成

功率放大器是一种电子设备&#xff0c;用于将输入信号的功率增加到更高的水平&#xff0c;以驱动负载或输出设备。它由多个组件和电路构成&#xff0c;以实现信号放大和传输。 下面是功率放大器的主要组成部分&#xff1a; 输入级&#xff1a;输入级是功率放大器的第一个阶段&a…

C++学习笔记“类和对象”:继承;

目录 4.6 继承 4.6.1 继承的基本语法 4.6.2 继承方式 4.6.3 继承中的对象模型 4.6.4 继承中构造和析构顺序 4.6.5 继承同名成员处理方式 4.6.6 继承同名静态成员处理方式 4.6.7 多继承语法 4.6.8 菱形继承 4.6 继承 继承是面向对象三大特性之一 有些类与类之间存在…

HTML+CSS 图片轮播卡片

效果演示 实现了一个图片轮播卡片的效果,包括一个容器(.container)、一个卡片(.card)、一个图片(.img)、一个内容区域(.content)和一个滑动条(.slider)。卡片包含一张图片和一些文本内容,图片可以通过滑动条进行切换。整个卡片具有圆角和阴影效果,使其看起来更加美…

嵌入式之存储基本知识

系列文章目录 嵌入式之存储基本知识 嵌入式之存储基本知识 系列文章目录一、RAM与ROM二、DRAM和SRAM三、SDRAM&#xff08;DRAM的一种&#xff09;四、DDR 一、RAM与ROM RAM&#xff08;随机存取存储器&#xff09;和ROM&#xff08;只读存储器&#xff09;是两种不同类型的计…

COMPUTEX 2024正式开启:华硕NUC带您领略全芯AI体验

6月4日&#xff0c;一年一度的台北国际电脑展&#xff08;COMPUTEX 2024&#xff09;在中国台北拉开序幕&#xff0c;以“AI串联&#xff0c;共创未来”为主题&#xff0c;将全球的科技企业汇聚于此&#xff0c;并推出多项新技术及产品。 华硕也在这场科技盛会中展示了多款创新…

Nvidia Jetson/Orin +FPGA+AI大算力边缘计算盒子:无人机自主飞行软件平台

案例简介 北京泛化智能科技有限公司&#xff08;gi&#xff09;所主导开发的 Generalized Autonomy Aviation System (GAAS) 是为无人机以及城市空中交通 (UAM, Urban Air Mobility) 所设计的开源无人机自主飞行框架。通过 SLAM、路径规划和 Global Optimization Graph 等功能…

wordpress里面嵌入哔哩哔哩视频的方法

我们正常如果从blibli获取视频分享链接然后在wordpress里面视频URL插入&#xff0c;发现是播放不了的 而视频嵌入代码直接粘贴呢窗口又非常的小 非常的难受&#xff0c;就需要更改一下代码。你可以在在allowfullscreen"true"的后面&#xff0c;留1个空格&#xff…