【蓝桥杯速成】| 11.回溯 之 子集问题

题目一:子集

问题描述

78. 子集 - 力扣(LeetCode)

给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。

解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。

示例 1:

输入:nums = [1,2,3]
输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]

示例 2:

输入:nums = [0]
输出:[[],[0]]

提示:

  • 1 <= nums.length <= 10
  • -10 <= nums[i] <= 10
  • nums 中的所有元素 互不相同

解题步骤

根据前面的做题经验,这一题应该比较容易AC

有没有觉得数组所有可能的子集很像我们每一层遍历的结果,

所以关于子集问题,我们需要的结果不是叶子结点,而是所有结点

那么其它代码逻辑不变,我们只需要改一下收集结果的位置即可

把result.push_back(path);这行代码从终止条件中拿出来

就表示我们每一步都会执行这一句,

空集是所有集合的子集,那么刚调用这个backtracking函数我们就会先加入[]

后面就是遍历一下就加入一下,输出顺序是纵深的,因为这里用的递归调用

对于终止条件,即用完数组所有元素,

那么我们用于指向遍历元素的startindex必然大于等于nums.size()

但其实也可以不加终止条件,因为我们的for循环会让i<nums.size(),它已经结束了

完整代码如下!

code

class Solution {
public:vector<int> path;vector<vector<int>> result;void backtracking(vector<int>& nums,int startindex){//返回的是每个结点result.push_back(path);if(startindex>=nums.size()){return;}for(int i=startindex;i<nums.size();i++){path.push_back(nums[i]);backtracking(nums,i+1);path.pop_back();}}vector<vector<int>> subsets(vector<int>& nums) {backtracking(nums,0);return result;}
};

题目二:子集②

问题描述

90. 子集 II - 力扣(LeetCode)

给你一个整数数组 nums ,其中可能包含重复元素,请你返回该数组所有可能的 子集(幂集)。

解集 不能 包含重复的子集。返回的解集中,子集可以按 任意顺序 排列。

示例 1:

输入:nums = [1,2,2]
输出:[[],[1],[1,2],[1,2,2],[2],[2,2]]

示例 2:

输入:nums = [0]
输出:[[],[0]]

提示:

  • 1 <= nums.length <= 10
  • -10 <= nums[i] <= 10

解题步骤

这题与上一题的区别就在于nums数组中可能包含重复元素

那么这个关键点和我们之前做过的组合总和②是一样的处理

重点就在于去重

我们需要排掉所有在同一层上相同的结果

但同时保证纵向不会被误判,因为纵向取数产生的数字重复,并不意味着答案重复

纵向是不断把子集变长的过程,加进来的都是从数组中取出的,

取出动作并不存在重复,哪怕数字一样但它不是从nums的同一位置取出的!

所以这一题我们要在单层遍历中加入去重代码即可

if(i>0 && nums[i]==nums[i-1] && used[i-1]==False)

为了方便判断重复元素,我们在主函数中会先对nums数组进行排序

那么遍历到第i个元素就可以通过 nums[i]==nums[i-1]这个代码判断是否出现重复元素

为了保证nums[i-1]合法,所以i必须大于0,

因为每次操作我们会用used数组标记数字的使用情况,

在纵向的递归中,used[i]=used[i-1]=true

但在同层当中,由于前一步存在回溯,我们的used[i-1]==false

翻译一下就是,上一层用过后放回去假装没用过

符合以上条件就是我们的重复元素,那么直接continue不需要继续执行

完整代码如下,需要注意在主函数中定义used数组和对nums数组进行排序!

code

class Solution {
public:vector<int> path;vector<vector<int>> result;void backtracking(vector<int>& nums,int startindex,vector<bool>& used){//返回的是每个结点result.push_back(path);for(int i=startindex;i<nums.size();i++){if(i>0 && nums[i]==nums[i-1] && used[i-1]==false){//去重continue;}path.push_back(nums[i]);used[i]=true;backtracking(nums,i+1,used);used[i]=false;path.pop_back();}}vector<vector<int>> subsetsWithDup(vector<int>& nums) {vector<bool> used(nums.size(), false);sort(nums.begin(),nums.end());backtracking(nums,0,used);return result;}
};

题目三:非递减子序列

问题描述

491. 非递减子序列 - 力扣(LeetCode)

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

解题步骤

这一题可以看成上一题的升级版,它在要求不重复的情况下同时要求该子序列递增

但需要注意的是这里的子序列是按照原数组排序生成的,

我们不能使用sort函数,不然结果也是不正确的

所以我们要换一种去重逻辑

但仍旧需要做到只除去同一层的重复项

不除去纵向的重复元素

那么排序不能用,used数组也就不能用了,

我们需要一个新的辅助,对于去重首选unordered_set,

可以利用find函数很快检查到是否已经出现过

那么我们在处理这一层元素前就需要先定义好这个uset

unordered_ser<int> uset;

再进入到遍历逻辑中,挨个检查元素是否符合题意

如果该元素之前已经用过,那么它必然可以在uset中找到

所以第一个不符合的情况是

if(uset.find(nums[i])!=uset.end())

要确保子序列递增,那么nums[i]不能小于当前path的最后一个元素,即path.back()

为防止出现path为空时的错误,先判断path.empty()为false

则第二个不符合情况如下

if(!path.empty() && nums[i]<path.back)

 可以合并这两种情况,continue

没有出现以上情况,则处理该结点

把nums[i]加入uset中做记录

再加入该数到path中

递归调用后回溯

uset.insert(nums[i]);

path.push_back(nums[i]);

backtracking(nums,i+1);

path.pop_back();

这里的uset不需要回溯,因为我们在每一层使用它,

如果是递归会重新定义,内容被清空不影响判断去重 

此外在加入结果到result数组中时,我们要先判断path.size()>=2,

这也是题目条件之一,要求子序列长度大于等于2

if(path.size()>=2){

        result.push_back(path);

}

组合所有代码,即可得到完整版如下方! 

code

class Solution {
public:vector<int> path;vector<vector<int>> result;void backtracking(vector<int>& nums,int startindex){if(path.size()>=2){result.push_back(path);}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();}}vector<vector<int>> findSubsequences(vector<int>& nums) {backtracking(nums,0);return result;}
};

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

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

相关文章

C# BULK INSERT导入大数据文件数据到SqlServer

BULK INSERT 的核心原理 BULK INSERT 是一种通过数据库原生接口高效批量导入数据的技术&#xff0c;其核心原理是绕过逐条插入的 SQL 解析和执行开销&#xff0c;直接将数据以二进制流或批量记录的形式传输到数据库。 在.NET中&#xff0c;主要通过 ​SqlBulkCopy 类​&#x…

Power BI嵌入应用:常见问题与调试技巧

将Power B 嵌入应用时的常见问题与调试技巧 Power BI Embedded 是一项 Microsoft Azure 服务&#xff0c;允许开发人员将交互式 Power BI 报表和仪表板嵌入到外部自定义应用程序或网站中。将Power BI嵌入应用程序能有效提升用户体验&#xff0c;但实施过程中可能面临一些典型问…

Android Studio编译问题

文章目录 GradleJDK版本不兼容 Gradle JDK版本不兼容 Incompatible because this component declares an API of a component compatible with Java 11 and the consumer needed a runtime of a component compatible with Java 8 查看module内gradle文件是否设置jdk版本&…

Four.meme是什么,一篇文章读懂

一、什么是Four.meme&#xff1f; Four.meme 是一个运行在 BNB 链的去中心化平台旨在为 meme 代币供公平启动服务。它允许用户以极低的成本创建和推出 meme 代币&#xff0c;无需预售或团队分配&#xff0c;它消除了传统的预售、种子轮和团队分配&#xff0c;确保所有参与者有…

解决PHP内存溢出问题的讨论和分析

PHP作为一种广泛使用的服务器端脚本语言&#xff0c;在处理大量数据或复杂任务时&#xff0c;常常会遇到内存溢出的问题。内存溢出不仅会导致程序崩溃&#xff0c;还可能影响服务器的稳定性。本文将探讨解决PHP内存溢出问题的最佳实践&#xff0c;并通过代码示例进行详细说明。…

git,openpnp - 根据安装程序打包名称找到对应的源码版本

文章目录 git,openpnp - 根据安装程序打包名称找到对应的源码版本概述笔记备注 - 提交时间不可以作为查找提交记录的依据END git,openpnp - 根据安装程序打包名称找到对应的源码版本 概述 想在openpnp官方最新稳定版上改一改&#xff0c;首先就得知道官方打包的安装程序对应的…

基于Spring Boot的停车场管理系统的设计与实现(LW+源码+讲解)

专注于大学生项目实战开发,讲解,毕业答疑辅导&#xff0c;欢迎高校老师/同行前辈交流合作✌。 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;…

基于Spring Boot + Vue的银行管理系统设计与实现

基于Spring Boot Vue的银行管理系统设计与实现 一、引言 随着金融数字化进程加速&#xff0c;传统银行业务向线上化转型成为必然趋势。本文设计并实现了一套基于Spring Boot Vue的银行管理系统&#xff0c;通过模块化架构满足用户、银行职员、管理员三类角色的核心业务需求…

Unity | Tag、Layer常量类生成工具

在项目开发中我们可以对诸如Layer、Tag等编辑器数据进行常量生成&#xff0c;来代替在代码中通过输入字符串生成常量的形式以提高开发效率。 Layer的生成可以通过LayerMask.LayerToName获取层名称&#xff08;也可以从TagManager.asset中获得 &#xff09;&#xff0c;Tag的生成…

两个手机都用流量,IP地址会一样吗?深入解析

在日常生活中&#xff0c;我们常常会同时使用多台手机设备上网&#xff0c;尤其是在流量充足的情况下。你是否曾好奇过&#xff0c;当两台手机同时使用流量上网时&#xff0c;它们的IP地址会是一样的吗&#xff1f;这个问题看似简单&#xff0c;却涉及移动网络的技术原理。本文…

后端——AOP异步日志

需求分析 在SpringBoot系统中&#xff0c;一般会对访问系统的请求做日志记录的需求&#xff0c;确保系统的安全维护以及查看接口的调用情况&#xff0c;可以使用AOP对controller层的接口进行增强&#xff0c;作日志记录。日志保存在数据库当中&#xff0c;为了避免影响接口的响…

Qt的内存管理机制

在Qt中&#xff0c;显式使用new创建的对象通常不需要显式调用delete来释放内存&#xff0c;这是因为Qt提供了一种基于对象树(Object Tree)和父子关系(Parent-Child Relationship)的内存管理机制。这种机制可以自动管理对象的生命周期&#xff0c;确保在适当的时候释放内存&…

React:React主流组件库对比

1、Material-UI | 官网 | GitHub | GitHub Star: 94.8k Material-UI 是一个实现了 Google Material Design 规范的 React 组件库。 Material UI 包含了大量预构建的 Material Design 组件&#xff0c;覆盖导航、滑块、下拉菜单等各种常用组件&#xff0c;并都提供了高度的可定制…

排序算法(插入,希尔,选择,冒泡,堆,快排,归并)

1.插入排序 插入排序的主要思想是额外申请一个空间cur&#xff0c;让cur一开始等于数组的第1号位置,设置i1&#xff0c;让i-1的元素与其比较&#xff0c;如果arr[i-1]>arr[i]&#xff0c;就让arr[i1] arr[i]&#xff0c;当进行到最后一次对比结束&#xff0c;i-1,再让arr[…

python学习笔记--实现简单的爬虫(二)

任务&#xff1a;爬取B站上最爱欢迎的编程课程 网址&#xff1a;编程-哔哩哔哩_bilibili 打开网页的代码模块&#xff0c;如下图&#xff1a; 标题均位于class_"bili-video-card__info--tit"的h3标签中&#xff0c;下面通过代码来实现&#xff0c;需要说明的是URL中…

Vue3 实现pdf预览

1.使用到的插件 vue3-pdf-app 以及预览效果 2.下载依赖 // 可以使用npm 以及pnpm // 下载版本1.0.3 pnpm install vue3-pdf-app^1.0.3 3.封装pdfModel组件复用 <template><VuePdfApp :page-scale"pageScale" :theme"theme" :style"width: …

SpringBoot集成Elasticsearch 7.x spring-boot-starter-data-elasticsearch 方式

SpringBoot集成Elasticsearch 7.x | spring-boot-starter-data-elasticsearch 方式 前言添加maven依赖配置application.properties测试实体类 方式一&#xff1a;继承 ElasticsearchRepository&#xff08;适合简单查询&#xff09; 直接使用想自定义自己的Repository接口 方式…

【Clang AST】基于 Clang 获取分析 AST

The Clang AST AST&#xff08;Abstract Syntax Tree&#xff09;抽象语法树 AST是什么 抽象语法树&#xff08;Abstract Syntax Tree, AST&#xff09;是源代码的抽象表示&#xff0c;广泛用于编译器和分析工具中。 AST将源代码的语法结构转换为树形结构&#xff0c;其中每…

onedav一为导航批量自动化导入网址(完整教程)

OneNav作为一个功能强大的导航工具,支持后台管理、加密链接、浏览器书签批量导入等功能,能够帮助用户轻松打造专属的导航页面。今天,我将为大家详细介绍如何实现OneNav导航站的批量自动化导入网址。 1、建立要批量导入的表格 格局需要创建表格,表格的要求是一定要有需要,…

文档处理控件Aspose.Words 教程:.NET版中增强的 AI 文档摘要功能

Aspose.Words是一个功能强大的 Word 文档处理库。它可以帮助开发人员自动编辑、转换和处理文档。 自 24.11 版以来&#xff0c;Aspose.Words for .NET 提供了 AI 驱动的文档摘要功能&#xff0c;使用户能够从冗长的文本中快速提取关键见解。在 25.2 版中&#xff0c;我们通过使…