力扣日记2.20-【回溯算法篇】491. 非递减子序列
力扣日记:【回溯算法篇】491. 非递减子序列
日期:2023.2.20
参考:代码随想录、力扣
ps:放了个寒假,日记又搁置了三星期……(下跪忏悔)
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
题解
cpp ver
class Solution {
public:vector<int> path;vector<vector<int>> result;vector<vector<int>> findSubsequences(vector<int>& nums) {// nums.size >= 2if (nums.size() < 2) return result;backtracking(nums, 0, -200); // -100 <= nums[i] <= 100return result;}void backtracking(vector<int>& nums, int startindex, int lastnum) {// 子序列至少有两个值if (path.size() >= 2) result.push_back(path);int used[201] = {0}; // 这里使用数组来进行去重操作,题目说数值范围[-100, 100],在for循环前重置,每个for循环对应一个// for 循环for (int i = startindex; i < nums.size(); i++) {// // 树层去重(如果本次取出元素与上一个元素一样,则跳过该元素)// if (i > startindex && nums[i] == nums[i - 1]) continue;// 注意,本题由于不能对元素进行排序,所以树层中也可能出现不连续元素重复的可能,所以不能简单的用相邻元素重复来去重// 可以用哈希表来去重(或数组)if (used[nums[i] + 100] != 0) continue; // 如果是已经取过的元素,则跳过该元素used[nums[i] + 100] = 1; // 记录该元素// 如果本次取出元素比上一次取的元素低,则不进入递归,但不结束for循环// (注意取值可不连续!!!如[4,7,6,7]中[4,7,7]也是递增子序列,所以这里不能break)if (nums[i] < lastnum) continue;// 处理节点path.push_back(nums[i]);backtracking(nums, i + 1, nums[i]);path.pop_back();}}
};
复杂度
时间复杂度: O(n * 2^n)
空间复杂度: O(n)
思路总结
- 本题首先要明确“递增子序列”的概念
- 子序列问题本质上是子集问题
- 递增子序列(或者说非递减子序列)是可以从原集合中非连续取值的!!!
- 这点是易错点,且单从题目描述或例子中不能得出此结论(但经过测试用例确实如此)
- 以[4,7,6,7]为例子,[4,7,7]或[7,7]也是其子序列(这是不同于只能连续取值的字符串子串的)
- 所以本题在去重时,不能像 90.子集 II 那样通过相邻元素相同来去重(那种去重思路仅适用于能先对原集合进行排序的情况,但本题提前排序会改变原集合的非递增性质故不能提前排序),因为可能会在不连续的地方出现重复的元素。
- 可以通过哈希表的方法来去重(如用哈希set或效率更高的数组),如代码所示
- 每层for循环都对应一个数组来记录某元素是否已经取过,如果已经取过,则跳过该元素,即:
int used[201] = {0}; // 这里使用数组来进行去重操作,题目说数值范围[-100, 100],在for循环前重置,每个for循环对应一个// for 循环for (int i = startindex; i < nums.size(); i++) {//用哈希表来去重(或数组)if (used[nums[i] + 100] != 0) continue; // 如果是已经取过的元素,则跳过该元素used[nums[i] + 100] = 1; // 记录该元素...
- 每层for循环都对应一个数组来记录某元素是否已经取过,如果已经取过,则跳过该元素,即:
- 可以通过哈希表的方法来去重(如用哈希set或效率更高的数组),如代码所示
- 对于需要为“递增子序列”的判断,实际上也是能否进行取值和递归(即所谓处理节点)的前提条件,即只有当前值不小于上一次取的值,才能进行取值和递归:
- 首先用
last_num
作为参数来记录上一次取的值,即在递归时令last_num = nums[i]
,并且在满足上面的去重条件后,通过if (nums[i] < lastnum) continue;
来过滤不满足递增条件的元素。 - 这里也可以不用
last_num
作为递归参数,而是用if (!path.empty() && nums[i] < path.back()) continue
来表示,因为path.back()
即为上一个取的值(前提是path不为空) - 同时注意不能用
break
而要用contnue
,理由是子序列的取值可以不连续,即使当前值不满足递增,其后面的元素也可能满足,因此不能直接break!!!
- 首先用
- 树形结构示意图
- 可见其中存在两种不符合条件的情况,一是“同一父节点下本层重复使用”,对应去重;二是“所取元素小于子序列最后一个元素”,对应“递增”条件。
- 三部曲:
- 返回值及传递参数:参数为经典的原数组
nums
以及startindex
记录for循环取值的起始位置,除此之外,还用一个last_num
记录递归纵向遍历中的上一个取值 (如果直接用path.back()
表示则不需要此参数) - 终止条件:对于子集问题,由于需要遍历各个节点进行存储,所以不需要专门的终止条件。这里注意子序列至少包含两个值,即path需要满足
size>=2
- 注:在原先的代码实现中,本来是在终止条件处实现递增条件的判断(即当出现小于上一个取值的元素,则终止),但是这样会使得最后一个path的存储非常麻烦,所以作废,还是需要将此递增条件的判断作为for循环中、处理节点(即取值并递归)的前提条件。
- for循环处理:
- 去重(哈希表记录重复元素,重复则跳过)
- 递增条件(小于上一个取值则跳过)
- 处理节点(取值、递归、回溯)
- 返回值及传递参数:参数为经典的原数组
相关文章:

力扣日记2.20-【回溯算法篇】491. 非递减子序列
力扣日记:【回溯算法篇】491. 非递减子序列 日期:2023.2.20 参考:代码随想录、力扣 ps:放了个寒假,日记又搁置了三星期……(下跪忏悔) 491. 非递减子序列 题目描述 难度:中等 给你一…...

Android 13.0 SystemUI下拉状态栏定制二 锁屏页面横竖屏解锁图标置顶显示功能实现
1.前言 在13.0的系统rom定制化开发中,在关于systemui的锁屏页面功能定制中,由于在平板横屏锁屏功能中,时钟显示的很大,并且是在左旁边居中显示的, 由于需要和竖屏显示一样,所以就需要用到小时钟显示,然后同样需要居中,所以就来分析下相关的源码,来实现具体的功能 如图…...

FPGA_简单工程_拨码开关
一 框图 二 波形图 三 代码 3.1 工程代码 module bomakiaguan (input [15:0] switch, // 输入16路拨码开关output reg [15:0] led // 输出16个LED灯 );always (switch) beginled < switch; // 将拨码开关的值直接赋给LED灯 end // 将拨码开关的值直接赋给LED灯 endmodu…...

LaunchPad 市场的复苏,Penpad 成新兴生力军
以 Fair Launch 为主要启动方式的铭文市场的爆发,推动了 LaunchPad 市场的复苏,绝多数所铭文项目都能通过 Fairr Launch 的方式筹集资金实现启动,该赛道的爆发不仅推动了数百亿美元的热钱开始在链上不断涌动,同时也进一步形成了新…...

知识图谱实战应用30-基于py2neo的天文学中的恒星、行星与卫星之间的关系知识图谱研究与应用
大家好,我是微学AI,今天给大家介绍一下知识图谱实战应用30-基于py2neo的天文学中的恒星、行星与卫星之间的关系知识图谱研究与应用。本文将详细介绍如何利用py2neo构建天文学中的恒星、行星与卫星之间的关系知识图谱,并探讨其在天文学研究中的应用。文章将提供多条太阳系中恒…...

笔试题详解(C语言进阶)
前言 欢迎阅读本篇文章!本篇文章通过一个笔试题来加强我们对C语言的理解,希望对你有帮助。后续我会写一个栏目,集合我见到的C语言题目,进行分析讲解。 1、题目一 判断下面程序的输出结果:(下面说的地址4/8字节是因为对…...

ClickHouse快速上手
简介 ClickHouse是一个用于联机分析(OLAP)的列式数据库管理系统(DBMS) 官网(https://clickhouse.com/docs/zh)给出的定义,其实没看懂 特性 ClickHouse支持一种基于SQL的声明式查询语言,它在许多情况下与ANSI SQL标准相同。使用时和MySQL有点相似&#…...

蓝桥杯DP算法——背包问题(C++)
目录 一、01背包问题 二、完全背包问题 三、多重背包问题 四、多重背包问题(优化版) 五、分组背包问题 一、01背包问题 01背包问题就是有N件物品,一个空间大小为V的背包,每个物品只能使用一次,使得背包中所装物品…...
【LeetCode+JavaGuide打卡】Day22|235. 二叉搜索树的最近公共祖先、701.二叉搜索树中的插入操作、450.删除二叉搜索树中的节点
学习目标: 235. 二叉搜索树的最近公共祖先 701.二叉搜索树中的插入操作 450.删除二叉搜索树中的节点 学习内容: 235. 二叉搜索树的最近公共祖先 题目链接&&文章讲解 给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最…...
Stable Diffusion WebUI 界面介绍
本文收录于《AI绘画从入门到精通》专栏,专栏总目录:点这里。 大家好,我是水滴~~ 本文主要对 Stable Diffusion WebUI 的界面进行简单的介绍,让你对该 WebUI 有个大致的了解,为后面的深入学习打下一个基础。主要内容包括:Stable Diffusion 模型(Stable Diffusion checkp…...

Cocos2dx-lua ScrollView[一]基础篇
一.ScrollView概述 cocos游戏中ScrollView控件大量使用,95%以上的项目都会使用ScrollView,个别游戏可能全部使用翻页的滑动效果。如果想要精通Cocos的UI开发,精通ScrollView控件非常关键,因此对ScrollView的使用进行总结很有必要。 下文缩写说明:sv = ScrollView, item代…...

QT应用软件【协议篇】周立功CAN接口卡代码示例
文章目录 USBCAN系列CAN接口卡规格参数资料下载QT引用周立功的库安装sdk代码USBCAN系列CAN接口卡 USBCAN系列CAN接口卡兼容USB2.0全速规范,可支持1/2/4/8路CAN接口。采用该接口卡,PC机可通过USB连入CAN网络,进行CAN总线数据采集和处理,主要具备以下几大优势特点: 支持车载…...

JVM对象的创建流程与内存分配
对象的创建流程与内存分配 创建流程对象内存分配方式内存分配安全问题对象内存分配流程【重要】:对象怎样才会进入老年代?重点 案例演示:对象分配过程大对象直接进入老年代02-对象内存分配的过程: 创建流程 加载 验证 解析 准备 初始化 使用 写在 对象内存分配方式 内存分配…...

docker (六)-进阶篇-数据持久化最佳实践MySQL部署
容器的数据挂载通常指的是将宿主机(虚拟机或物理机)上的目录或文件挂载到容器内部 MySQL单节点安装 详情参考docker官网文档 1 创建对应的数据目录、日志目录、配置文件目录(参考二进制安装,需自己建立数据存储目录) mkdir -p /data/mysq…...

力扣题目训练(17)
2024年2月10日力扣题目训练 2024年2月10日力扣题目训练551. 学生出勤记录 I557. 反转字符串中的单词 III559. N 叉树的最大深度241. 为运算表达式设计优先级260. 只出现一次的数字 III126. 单词接龙 II 2024年2月10日力扣题目训练 2024年2月10日第十七天编程训练,今…...
【react】react中和vue中的provide/inject、context写法示例
react写法 在 React 中,provide和inject的功能类似于 Vue.js 中的 provide和inject。它们都是用于跨组件层次传递数据的。 在 React 中,没有内置的 provide 和 inject 函数。但是,你可以使用 React 的 Context 来实现类似的功能。 Context…...
MySQL 的存储引擎(基本介绍)
文章目录 前言MySQL 的存储引擎介绍存储引擎是什么?存储引擎的特性? Innodb 与 Mylsam 的区别行级锁与表级锁是否支持事务是否支持恢复数据是否支持外键是否支持 MVCC 总结 前言 好文章不要错过,前两天跟大家分享的文章 1.MySQL的基础架构 2.SQL语句的…...
Unity3D 实现基于物理引擎的绳子关节解析详解
前言 在游戏开发中,有时候我们需要实现绳子关节效果,比如在射击游戏中射击绳子,或者在平衡游戏中使用绳子作为支撑。本文将详细介绍如何使用Unity3D的物理引擎实现绳子关节效果。 对惹,这里有一个游戏开发交流小组,希…...

C语言二级易忘易错易混知识点(自用)
1.数组名不能自加。 因为数组名实际上是一个指针,指向数组的第一个元素的地址。数组名在编译器中被视为常量,它的值是固定的,不能改变。 要访问数组的不同元素,应该使用数组名加上偏移量的方式来访问。 2.共用体只有最后一次赋值…...

js_三种方法实现深拷贝
深拷贝( 递归 ) 适用于需要完全独立于原始对象的场景,特别是当对象内部有引用类型时,为了避免修改拷贝后的对象影响到原始对象,就需要使用深拷贝。 // 原始对象 const obj { uname: Lily,age: 19,hobby: [乒乓球, 篮球…...

华为云AI开发平台ModelArts
华为云ModelArts:重塑AI开发流程的“智能引擎”与“创新加速器”! 在人工智能浪潮席卷全球的2025年,企业拥抱AI的意愿空前高涨,但技术门槛高、流程复杂、资源投入巨大的现实,却让许多创新构想止步于实验室。数据科学家…...
谷歌浏览器插件
项目中有时候会用到插件 sync-cookie-extension1.0.0:开发环境同步测试 cookie 至 localhost,便于本地请求服务携带 cookie 参考地址:https://juejin.cn/post/7139354571712757767 里面有源码下载下来,加在到扩展即可使用FeHelp…...
椭圆曲线密码学(ECC)
一、ECC算法概述 椭圆曲线密码学(Elliptic Curve Cryptography)是基于椭圆曲线数学理论的公钥密码系统,由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA,ECC在相同安全强度下密钥更短(256位ECC ≈ 3072位RSA…...

前端开发面试题总结-JavaScript篇(一)
文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包(Closure)?闭包有什么应用场景和潜在问题?2.解释 JavaScript 的作用域链(Scope Chain) 二、原型与继承3.原型链是什么?如何实现继承&a…...

(转)什么是DockerCompose?它有什么作用?
一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用,而无需手动一个个创建和运行容器。 Compose文件是一个文本文件,通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...

【开发技术】.Net使用FFmpeg视频特定帧上绘制内容
目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法,当前调用一个医疗行业的AI识别算法后返回…...

2025季度云服务器排行榜
在全球云服务器市场,各厂商的排名和地位并非一成不变,而是由其独特的优势、战略布局和市场适应性共同决定的。以下是根据2025年市场趋势,对主要云服务器厂商在排行榜中占据重要位置的原因和优势进行深度分析: 一、全球“三巨头”…...

浪潮交换机配置track检测实现高速公路收费网络主备切换NQA
浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求,本次涉及的主要是收费汇聚交换机的配置,浪潮网络设备在高速项目很少,通…...

计算机基础知识解析:从应用到架构的全面拆解
目录 前言 1、 计算机的应用领域:无处不在的数字助手 2、 计算机的进化史:从算盘到量子计算 3、计算机的分类:不止 “台式机和笔记本” 4、计算机的组件:硬件与软件的协同 4.1 硬件:五大核心部件 4.2 软件&#…...

AI语音助手的Python实现
引言 语音助手(如小爱同学、Siri)通过语音识别、自然语言处理(NLP)和语音合成技术,为用户提供直观、高效的交互体验。随着人工智能的普及,Python开发者可以利用开源库和AI模型,快速构建自定义语音助手。本文由浅入深,详细介绍如何使用Python开发AI语音助手,涵盖基础功…...