当前位置: 首页 > news >正文

代码随想录算法训练营第二十八天 | 491.递增子序列,46.全排列,47.全排列 II

一、参考资料

递增子序列

题目链接/文章讲解:https://programmercarl.com/0491.%E9%80%92%E5%A2%9E%E5%AD%90%E5%BA%8F%E5%88%97.html

视频讲解:https://www.bilibili.com/video/BV1EG4y1h78v

全排列

题目链接/文章讲解:https://programmercarl.com/0046.%E5%85%A8%E6%8E%92%E5%88%97.html

视频讲解:https://www.bilibili.com/video/BV19v4y1S79W

全排列 II

题目链接/文章讲解:https://programmercarl.com/0047.%E5%85%A8%E6%8E%92%E5%88%97II.html

视频讲解:https://www.bilibili.com/video/BV1R84y1i7Tm

二、LeetCode491.递增子序列

https://leetcode.cn/problems/non-decreasing-subsequences/description/

给你一个整数数组 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]]

切割问题可以抽象为树型结构,如图:

class Solution {
private:vector<int> path;vector<vector<int>> res;void backtracking(vector<int>& nums, int startIndex) {if (path.size() > 1) {res.push_back(path);}unordered_set<int> uset;for (int i = startIndex; i < nums.size(); i++) {if ((!path.empty() && nums[i] < path.back()) || uset.find(nums[i]) != uset.end()) {continue;}uset.insert(nums[i]);path.push_back(nums[i]);backtracking(nums, i + 1);path.pop_back();}}
public:vector<vector<int>> findSubsequences(vector<int>& nums) {backtracking(nums, 0);return res;}
};

带注释版:

// 版本一
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);// 注意这里不要加return,要取树上的节点}unordered_set<int> uset; // 使用set对本层元素进行去重for (int i = startIndex; i < nums.size(); i++) {if ((!path.empty() && nums[i] < path.back())|| uset.find(nums[i]) != uset.end()) {continue;}uset.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;}
};

优化版本【用数组做哈希表】

// 版本二
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);}int used[201] = {0}; // 这里使用数组来进行去重操作,题目说数值范围[-100, 100]for (int i = startIndex; i < nums.size(); i++) {if ((!path.empty() && nums[i] < path.back())|| used[nums[i] + 100] == 1) {continue;}used[nums[i] + 100] = 1; // 记录这个元素在本层用过了,本层后面不能再用了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;}
};

三、LeetCode46.全排列

https://leetcode.cn/problems/permutations/description/

给定一个不含重复数字的数组 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 中的所有整数 互不相同
class Solution {
public:vector<vector<int>> result;vector<int> path;void backtracking (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] == true) continue; // path里已经收录的元素,直接跳过used[i] = true;path.push_back(nums[i]);backtracking(nums, used);path.pop_back();used[i] = false;}}vector<vector<int>> permute(vector<int>& nums) {result.clear();path.clear();vector<bool> used(nums.size(), false);backtracking(nums, used);return result;}
};

排列问题的不同:

  • 每层都是从0开始搜索而不是startIndex

  • 需要used数组记录path里都放了哪些元素了

我写的如下~【唔,理解了思路】

class Solution {
private:vector<int> path;vector<vector<int>> res;void backtracking (vector<int>& nums, vector<bool>& used) {if (path.size() == nums.size()) {res.push_back(path);return ;}// unordered_set<int> uset;for (int i = 0; i < nums.size(); i++) {if (used[i]) continue;path.push_back(nums[i]);used[i] = true;backtracking(nums, used);used[i] = false;path.pop_back();}}public:vector<vector<int>> permute(vector<int>& nums) {vector<bool> used(nums.size(), false);backtracking(nums, used);return res;}
};

四、LeetCode47.全排列 II

https://leetcode.cn/problems/permutations-ii/description/

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

40.组合总和II (opens new window)90.子集II (opens new window)我们分别详细讲解了组合问题和子集问题如何去重。

那么排列问题其实也是一样的套路。

还要强调的是去重一定要对元素进行排序,这样我们才方便通过相邻的节点来判断是否重复使用了

带注释版:

class Solution {
private:vector<vector<int>> result;vector<int> path;void backtracking (vector<int>& nums, vector<bool>& used) {// 此时说明找到了一组if (path.size() == nums.size()) {result.push_back(path);return;}for (int i = 0; i < nums.size(); i++) {// used[i - 1] == true,说明同一树枝nums[i - 1]使用过// used[i - 1] == false,说明同一树层nums[i - 1]使用过 // 如果同一树层nums[i - 1]使用过则直接跳过if (i > 0 && nums[i] == nums[i - 1] && used[i - 1] == false) {continue;}if (used[i] == false) {used[i] = true;path.push_back(nums[i]);backtracking(nums, used);path.pop_back();used[i] = false;}}}
public:vector<vector<int>> permuteUnique(vector<int>& nums) {result.clear();path.clear();sort(nums.begin(), nums.end()); // 排序vector<bool> used(nums.size(), false);backtracking(nums, used);return result;}
};

图中我们对同一树层,前一位(也就是nums[i-1])如果使用过,那么就进行去重。

一般来说:组合问题和排列问题是在树形结构的叶子节点上收集结果,而子集问题就是取树上所有节点的结果

我写的这个题的代码:

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

拓展:

去重的关键部分代码:

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

如果改成 used[i - 1] == true, 也是正确的!,去重代码如下:

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

这是为什么呢,就是上面我刚说的,如果要对树层中前一位去重,就用used[i - 1] == false,如果要对树枝前一位去重用used[i - 1] == true。

对于排列问题,树层上去重和树枝上去重,都是可以的,但是树层上去重效率更高!

例子:[1,1,1]

(1) 树层上去重(used[i - 1] == false),的树形结构如下:

(2) 树枝上去重(used[i - 1] == true)的树型结构如下:

因此,树层上对前一位去重非常彻底,效率很高,树枝上对前一位去重虽然最后可以得到答案,但是做了很多无用搜索。

今日总结:

2023-02-14 终于补完了代码和博客~

回溯专题马上就结束辽,今天下午再把三个难题争取克服一下,晚上开始写贪心题目、复习数组专题,今日目标就是赶上进度!

下集预告:

● 332.重新安排行程

● 51. N皇后

● 37. 解数独

● 回溯专题总结

继续加油哈小赵~

相关文章:

代码随想录算法训练营第二十八天 | 491.递增子序列,46.全排列,47.全排列 II

一、参考资料递增子序列题目链接/文章讲解&#xff1a;https://programmercarl.com/0491.%E9%80%92%E5%A2%9E%E5%AD%90%E5%BA%8F%E5%88%97.html 视频讲解&#xff1a;https://www.bilibili.com/video/BV1EG4y1h78v 全排列题目链接/文章讲解&#xff1a;https://programmercarl.…...

使用 Three.js 后处理的粗略铅笔画效果

本文使用Three.js的后处理创建粗略的铅笔画效果。我们将完成创建自定义后处理渲染通道、在 WebGL中实现边缘检测、将法线缓冲区重新渲染到渲染目标以及使用生成和导入的纹理调整最终结果的步骤。翻译自Codrops&#xff0c;有改动。 Three.js 中的后处理 Three.js中的后处理是一…...

推荐一些不常见的搜索引擎

5.雅虎网来自 Yahoo.com 的屏幕截图&#xff0c;2023 年 2 月截至 2022 年 1 月&#xff0c;Yahoo.com&#xff08;Verizon Media&#xff09;的搜索市场份额为 11.2%。雅虎的优势在于多元化&#xff0c;除搜索外还提供电子邮件、新闻、金融等服务。二十多年来&#xff0c;雅虎…...

RabbitMQ工作模式

目录1.Work queues工作队列模式1.1 模式说明1.2 代码1.3 测试1.4 小结2.订阅模式类型3.Publish/Subscribe发布与订阅模式3.1 模式说明3.2 代码3.3 测试3.4 小结4.Routing路由模式4.1 模式说明4.2 代码4.3 测试4.4 小结5.Topics通配符模式5.1 模式说明5.2 代码5.3 测试5.4 小结6…...

机器学习在预测脊髓型颈椎病中的应用:一项28名参与者的事后初步研究

机器学习在预测脊髓型颈椎病中的应用:一项28名参与者的事后初步研究 Machine Learning for the Prediction of Cervical Spondylotic Myelopathy: A Post Hoc Pilot Study of 28 Participants 简单说&#xff1a;训练了两个模型&#xff1a;1)预测脊髓型颈椎病诊断&#xff0…...

【智能计算数学】微积分

高数问题解决流程引例&#xff1a;回归回归引例&#xff1a;分类分类线性可分FLD线性不可分智能计算讨论范围下降法为什么要用下降法&#xff1f;- 解析解很难写出公式或很复杂难计算有哪些常用的下降法&#xff1f;- 梯度下降&高斯-牛顿法梯度下降&#xff08;Gradient De…...

win10+RTX4070ti+libtorch部署

环境cuda 11.7、cudnn8.6.0、libtorch1.13.1cu117 注意&#xff1a; 1&#xff09;libtorch官网进不去的可直接下载 Release version https://download.pytorch.org/libtorch/cu117/libtorch-win-shared-with-deps-1.13.1%2Bcu117.zip Debug version https://download.pytorch.…...

【Python百日进阶-Web开发-Vue3】Day518 - Vue+ts后台项目5:用户列表

文章目录 一、获取用户列表的数据1.1 定义用户列表和角色列表的接口src/request/api.ts1.2 获取用户列表数据src/views/UserView.vue二、定义用户列表数据类型2.1 src/type/user.ts三、展示用户列表内容3.1 element-plus中的Select 选择器3.2 element-plus中的表格插槽3.3 展示…...

Linux内核转储---kdump原理梳理

文章目录Kexec和Kdump设计的区别kexeckdumpKdump的执行流程kexec的实现用户空间kexec内核空间vmcoreKdump的实现可以分为两部分&#xff1a;内核和用户工具。内核提供机制&#xff0c;用户工具在这些机制上实现各种转储策略&#xff0c;内核机制对用户工具的接口是一个系统调用…...

【C++】从0到1入门C++编程学习笔记 - 实战篇:演讲比赛流程管理系统

文章目录一、演讲比赛程序需求1.1 比赛规则1.2 程序功能1.3 程序效果图&#xff1a;二、项目创建2.1 创建项目2.2 添加文件三、创建管理类3.1创建文件3.2 头文件实现3.3 源文件实现四、菜单功能4.1 添加成员函数4.2 菜单功能实现4.3 测试菜单功能五、退出功能5.1 提供功能接口5…...

04 OpenCV位平面分解

1 基本概念 位平面分解的核心思想是将图像的每一个像素分解为多个二进制位&#xff0c;分别存储在不同的位平面上。例如&#xff0c;如果一个图像是8位深度的&#xff0c;则可以分解为8个位平面&#xff0c;每个位平面上存储一个二进制位。 位平面分解在图像压缩中有着重要的…...

Onvif协议如何判断摄像机支持 —— 筑梦之路

有人就问什么是Onvif协议呢&#xff1f; 全称为&#xff1a;Open Network Video Interface Forum.缩写成Onvif。 翻译过来是&#xff1a;开放型网络视频接口论坛&#xff0c;目的是确保不同安防厂商的视频产品能够具有互通性&#xff0c;这样对整体安防行业才是良性发展。 现…...

情人节new一个对象给你

今天情人节&#xff0c;有没对象的吗&#xff1f;假设你不知道new怎么用&#xff0c;每个人都有两种身份&#xff0c;一种没对象的人&#xff0c;这个时候new一个对象给你&#xff0c;一种是有对象的人&#xff0c;这个delete对象。等你学完这个new和delete知识点&#xff0c;无…...

linux篇【15】:应用层-网络https协议

目录 一.HTTPS介绍 1.HTTPS 定义 2.HTTP与HTTPS &#xff08;1&#xff09;端口不同&#xff0c;是两套服务 &#xff08;2&#xff09;HTTP效率更高&#xff0c;HTTPS更安全 3.加密&#xff0c;解密&#xff0c;密钥 概念 4.为什么要加密&#xff1f; 5.常见的加密方式…...

索引-性能分析-explain

explain 执行计划 explain 执行计划各字段含义 1&#xff09;id 就是代表 sql 的执行顺序或者表的执行顺序&#xff1b;id相同从上往下执行&#xff0c;id不同&#xff0c;id值越大越先执行&#xff1b;&#xff08;注&#xff1a;有子查询时就会出现sql执行顺序&#xff09;…...

mbedtls加密组件使用示例

1 mbedtls aes组件的使用 1.1 AES ECB加解密接口使用 int main(int argc, char *argv[]) {char key[256];char *inbuf calloc(1, 257);char *outbuf calloc(1, 257);char *buf calloc(1,257);char *tmp_outbuf outbuf;char *tmp_buf buf;mbedtls_aes_context aes_ctx;mb…...

如何量测太阳光模拟器的光谱致合度?

太阳模拟器是根据国际法规JIS、IEC60904、美国材料试验协会开发设计的AAA级太阳模拟器。对于100毫米100毫米和200毫米200毫米的光斑尺寸&#xff0c;光斑强度的输出功率范围可以从0.1到1太阳光强度。此外&#xff0c;还提供了灵活的出光方向&#xff0c;以满足用户的研究需求&a…...

网络安全领域中CISP证书八大类都有什么

CISP​注册信息安全专业人员 注册信息安全专业人员&#xff08;Certified Information Security Professional&#xff09;&#xff0c;是经中国信息安全产品测评认证中心实施的国家认证&#xff0c;对信息安全人员执业资质的认可。该证书是面向信息安全企业、信息安全咨询服务…...

17- 梯度提升回归树GBRT (集成算法) (算法)

梯度提升回归树: 梯度提升回归树是区别于随机森林的另一种集成方法&#xff0c;它的特点在于纠正与加强&#xff0c;通过合并多个决策树来构建一个更为强大的模型。该模型即可以用于分类问题&#xff0c;也可以用于回归问题中。在该模型中&#xff0c;有三个重要参数分别为 n_…...

05 OpenCV色彩空间处理

色彩空间&#xff08;Color Space&#xff09;是一种用于描述颜色的数学模型&#xff0c;它将颜色表示为多维向量或坐标&#xff0c;通常由三个或四个独立的分量来表示。不同的色彩空间在颜色的表示方式、可表达颜色的范围、计算速度和应用场景等方面存在差异&#xff0c;不同的…...

Mac软件卸载指南,简单易懂!

刚和Adobe分手&#xff0c;它却总在Library里给你写"回忆录"&#xff1f;卸载的Final Cut Pro像电子幽灵般阴魂不散&#xff1f;总是会有残留文件&#xff0c;别慌&#xff01;这份Mac软件卸载指南&#xff0c;将用最硬核的方式教你"数字分手术"&#xff0…...

Mac下Android Studio扫描根目录卡死问题记录

环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中&#xff0c;提示一个依赖外部头文件的cpp源文件需要同步&#xff0c;点…...

C++使用 new 来创建动态数组

问题&#xff1a; 不能使用变量定义数组大小 原因&#xff1a; 这是因为数组在内存中是连续存储的&#xff0c;编译器需要在编译阶段就确定数组的大小&#xff0c;以便正确地分配内存空间。如果允许使用变量来定义数组的大小&#xff0c;那么编译器就无法在编译时确定数组的大…...

智能AI电话机器人系统的识别能力现状与发展水平

一、引言 随着人工智能技术的飞速发展&#xff0c;AI电话机器人系统已经从简单的自动应答工具演变为具备复杂交互能力的智能助手。这类系统结合了语音识别、自然语言处理、情感计算和机器学习等多项前沿技术&#xff0c;在客户服务、营销推广、信息查询等领域发挥着越来越重要…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

站群服务器的应用场景都有哪些?

站群服务器主要是为了多个网站的托管和管理所设计的&#xff0c;可以通过集中管理和高效资源的分配&#xff0c;来支持多个独立的网站同时运行&#xff0c;让每一个网站都可以分配到独立的IP地址&#xff0c;避免出现IP关联的风险&#xff0c;用户还可以通过控制面板进行管理功…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

Unity中的transform.up

2025年6月8日&#xff0c;周日下午 在Unity中&#xff0c;transform.up是Transform组件的一个属性&#xff0c;表示游戏对象在世界空间中的“上”方向&#xff08;Y轴正方向&#xff09;&#xff0c;且会随对象旋转动态变化。以下是关键点解析&#xff1a; 基本定义 transfor…...

jdbc查询mysql数据库时,出现id顺序错误的情况

我在repository中的查询语句如下所示&#xff0c;即传入一个List<intager>的数据&#xff0c;返回这些id的问题列表。但是由于数据库查询时ID列表的顺序与预期不一致&#xff0c;会导致返回的id是从小到大排列的&#xff0c;但我不希望这样。 Query("SELECT NEW com…...

[特殊字符] 手撸 Redis 互斥锁那些坑

&#x1f4d6; 手撸 Redis 互斥锁那些坑 最近搞业务遇到高并发下同一个 key 的互斥操作&#xff0c;想实现分布式环境下的互斥锁。于是私下顺手手撸了个基于 Redis 的简单互斥锁&#xff0c;也顺便跟 Redisson 的 RLock 机制对比了下&#xff0c;记录一波&#xff0c;别踩我踩过…...