代码随想录算法训练营day29

题目:491.递增子序列、46.全排列、47.全排列 II

参考链接:代码随想录

491.递增子序列

思路:一开始按照基本回溯的模板来写。当路径长度大于2时加入ans,结束条件为开始位置到达末尾。for循环部分遍历第一个加入path中的数,如果目前的数小于path末尾,则直接考虑下一个数。写完后运行发现没有去重处理,但本题的去重和上题集合2不同,不能排序,不是相邻也可能重复,比如[4,4,5,4],会产生3个[4,4],去重方法我一开始没想到。
一开始的错误代码:

class Solution {
public: vector<vector<int>> ans;vector<int> path;void backtracking(vector<int>& nums,int begin){//begin为开始取的位置if(path.size()>=2){ans.push_back(path);}if(begin==nums.size()){return;}for(int i=begin;i<=nums.size()-1;i++){if(path.size()>0&&nums[i]<path.back()){//如果目前遍历的数小于path末尾,则不满足递增情况,直接考虑下一个数continue;}path.push_back(nums[i]);backtracking(nums,i+1);path.pop_back();}}vector<vector<int>> findSubsequences(vector<int>& nums) {backtracking(nums,0);return ans;}
};

看了解析需要对每一层进行去重,由于重复元素不相邻,只能用集合来判断重复。不能再简单的用used数组了。时间复杂度O(n*2^n)。
标答:

class Solution {
public: vector<vector<int>> ans;vector<int> path;void backtracking(vector<int>& nums,int begin){//begin为开始取的位置if(path.size()>=2){ans.push_back(path);}if(begin==nums.size()){return;}unordered_set<int> set;//对本层去重for(int i=begin;i<=nums.size()-1;i++){if(path.size()>0&&nums[i]<path.back()||set.find(nums[i])!=set.end()){//如果目前遍历的数小于path末尾,则不满足递增情况,直接考虑下一个数。或者在同一层出现重复。continue;}path.push_back(nums[i]);set.insert(nums[i]);backtracking(nums,i+1);path.pop_back();//这里不需要set中移出nums[i],因为是对整层的去重}}vector<vector<int>> findSubsequences(vector<int>& nums) {backtracking(nums,0);return ans;}
};

注意使用set在回溯的时候不用移出元素,因为是对整层去重。set也是每一层for循环之前定义一个。
看了标答,发现由于题目说了数值范围[-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);}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;}
};

46.全排列

思路:排列的组合的最大区别就是有顺序的考虑。比如第一个元素选的2,那么后面1和3还需要考虑,而组合就只需要考虑3了。所以在回溯模板的区别中,首先是for循环必须每次都是从0到结束,那么如何判断那些元素可以选呢?我们继续采用used数组,当for遍历的元素已经用过,则直接continue,否则加入路径。当路径长度为数组长度时将路径添加到ans。时间复杂度O(n*n!),注意这个时间复杂度就是所有排列方式的数量A(n,n)乘以生成每一个答案需要的n次push_back。

class Solution {
public:vector<vector<int>> ans;vector<int> path;void backtracking(vector<int>& nums,vector<int>& used){if(path.size()==nums.size()){ans.push_back(path);return;}for(int i=0;i<nums.size();i++){//每次都要全部遍历if(used[i]==1){continue;}path.push_back(nums[i]);used[i]=1;backtracking(nums,used);path.pop_back();used[i]=0;}}vector<vector<int>> permute(vector<int>& nums) {vector<int> used(nums.size(),0);backtracking(nums,used);return ans;}
};

47.全排列 II

思路:一开始想的就是在上题基础上加一个每层去重,由于排列每次for都要遍历所有元素,不是相邻情况,故每层使用了一个set去重。

class Solution {
public:vector<vector<int>> ans;vector<int> path;void backtracking(vector<int>& nums,vector<int>& used){if(path.size()==nums.size()){ans.push_back(path);}unordered_set<int> set;for(int i=0;i<nums.size();i++){//每一层去重,这里不是相邻重复情况使用setif(used[i]==1||set.find(nums[i])!=set.end()){continue;}path.push_back(nums[i]);used[i]=1;set.insert(nums[i]);backtracking(nums,used);path.pop_back();used[i]=0;}}vector<vector<int>> permuteUnique(vector<int>& nums) {vector<int> used(nums.size(),0);backtracking(nums,used);return ans;}
};

看完标答,发现可以先排序,然后只用一个used就可以完成所有功能。判断相邻方法和之前的组合一样。时间复杂度O(n*n!)。

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

对于回溯算法的时间复杂度,可以直接看这里。

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

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

相关文章

计讯物联智慧工业园区系统平台全面提升园区智能化水平

工业园区聚集着各种生产要素&#xff0c;是纺织、机械、家具等诸多产业集中的区域&#xff0c;更是资源消耗和污染物排放的集中地。根据某些工业园区环境调研&#xff0c;园区入驻企业从生产原料到生产制造过程大多带有有毒有害、易燃易爆的特性&#xff0c;再加上装置大型化、…

SpringBoot 热部署。

SpringBoot 热部署。 文章目录 SpringBoot 热部署。 pom.xml。 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional…

LeetCode-第137题-只出现一次的数||

1.题目描述 给你一个整数数组 nums &#xff0c;除某个元素仅出现 一次 外&#xff0c;其余每个元素都恰出现 三次 。请你找出并返回那个只出现了一次的元素。 你必须设计并实现线性时间复杂度的算法且使用常数级空间来解决此问题。 2.样例描述 3.思路描述 先把数组排序&am…

M2TS转MP4怎么转?超快的方法~

M2TS格式的优点主要体现在对高清视频的完美支持&#xff0c;能够提供极致的视觉体验。然而&#xff0c;由于其相对较大的文件大小&#xff0c;有时可能不太适合网络传输。此外&#xff0c;部分不支持M2TS的播放设备可能导致一定的兼容性问题。 想要播放m2ts视频&#xff0c;可…

【kubernetes】关于k8s集群如何将pod调度到指定node节点?

目录 一、k8s的watch机制 二、scheduler的调度策略 Predicate&#xff08;预选策略&#xff09; 常见算法&#xff1a; priorities&#xff08;优选策略&#xff09;常见的算法有&#xff1a; 三、k8s的标签管理之增删改查 四、k8s的将pod调度到指定node的方法 方案一&am…

DFS回溯-经典全排列问题(力扣)

前言 对于全排列问题&#xff0c;常用的做法是设置一个vis数组来确定位置i上的数字是否被访问&#xff0c;因为是全排列问题&#xff0c;所以不同的顺序也是不一样的排列&#xff0c;因此每次都是从起点开始询问**(注意起点到底是0还是1)** 46全排列(最简单的模板) class So…

Object.assign 这算是深拷贝吗

在JavaScript中&#xff0c;Object.assign() 是一个用于合并对象属性的常见方法。然而&#xff0c;对于许多开发者来说&#xff0c;关于它是否执行深拷贝的认识可能存在一些混淆。先说答案Object.assign() 不属于深拷贝&#xff0c;我们接着往下看。 Object.assign() 概览 首…

某资产管理系统打点过程中的免杀经历

上周&#xff0c;被扔过来单位内部的一个链接&#xff0c;让渗透一下&#xff0c;本以为三下五除二很快就能测完&#xff0c;没想到在对抗杀软时费了一番功夫&#xff0c;再加上杂七杂八的事儿&#xff0c;经过了一个星期才测完(&#xff03;&#xffe3;&#xff5e;&#xff…

贪心 Leetcode 45 跳跃游戏II

跳跃游戏II Leetcode 45 学习记录自代码随想录 给定一个长度为 n 的 0 索引整数数组 nums。初始位置为 nums[0]。 每个元素 nums[i] 表示从索引 i 向前跳转的最大长度。换句话说&#xff0c;如果你在 nums[i] 处&#xff0c;你可以跳转到任意 nums[i j] 处: 0 < j < …

C#知识点-21(初识数据库)

数据库与内存、文件的比较 内存&#xff1a; 优点&#xff1a;存取速度快 缺点&#xff1a;-容量小 -断电后&#xff0c;数据不会保存 文件&#xff1a; 优点&#xff1a;数据可以持久化保存 缺点&#xff1a;-读取速度慢…

mprpc分布式RPC网络通信框架

mprpc 项目介绍 该项目是一个基于muduo、Protobuf和Zookeeper实现的轻量级分布式RPC网络通信框架。 可以把任何单体架构系统的本地方法调用&#xff0c;重构成基于TCP网络通信的RPC远程方法调用&#xff0c;实现同一台机器的不同进程之间的服务调用&#xff0c;或者不同机器…

下载无水印抖音视频

在抖音看到某些视频想下载&#xff0c;却出现无法保存在本地【显示"作品暂时无法保存,链接已复制"】。或者下载的视频有水印。 而某些微信小程序下载可能需要付费或者有水印。其实我们可以直接使用电脑浏览器直接下载。 举个例子: 这是来自王道官方账号的一条视频链…

基于springboot的某大学外卖系统的实现(源码+论文)

文章目录 目录 文章目录 前言 一、功能设计 二、功能实现 1 后台登录 2管理员界面 3员工信息管理 4客户信息管理 三、库表设计 四、论文 前言 如今&#xff0c;信息化不断的高速发展&#xff0c;社会也跟着不断进步&#xff0c;现今的社会&#xff0c;各种工作都离不开信息化技…

Python基础二

一、变量 在编程中&#xff0c;变量是用来存储数据值的名称。在 Python 中&#xff0c;变量是动态类型的&#xff0c;这意味着你可以将任何类型的数据分配给一个变量&#xff0c;而不需要提前声明变量的类型。 1、全局变量 在函数外部定义的变量是全局变量&#xff0c;可以在程…

boost 编译

参考博客&#xff1a;vs2019 boost 入坑指南 boost下载 官方网站&#xff1a;https://www.boost.org/ 下面以boost_1_73_0为例&#xff1a; boost编译 解压boost_1_73_0.zip运行bootstrap.bat&#xff08;此时目录下会生成b2.exe&#xff09;编译boost b2 install --build…

【vue2项目总结】——动态渲染

文章目录 主页渲染封装接口页面调用传到子组件 搜索列表渲染根据关键字搜索分类id搜索 主页渲染 封装接口 封装准备接口 api/home.js import request from /utils/request// 获取首页数据 export const getHomeData () > {return request.get(/page/detail, {params: {p…

springboot3.x集成SpringDoc Swagger3

近期将springboox2.x升级到了3.x&#xff0c;索性将swagger2也同步升级到swagger3&#xff0c;具体过程如下。 一、添加maven依赖 <dependency><groupId>org.springdoc</groupId><artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>…

详解Java中的注解

在Java中&#xff0c;注解(Annotation)引入始于Java5&#xff0c;用来描述Java代码的元信息&#xff0c;通常情况下注解不会直接影响代码的执行&#xff0c;尽管有些注解可以用来做到影响代码执行。 注解可以做什么 Java中的注解通常扮演以下角色 编译器指令构建时指令运行时…

信息系统项目管理

信息系统项目管理 文章目录 信息系统项目管理前言一、信息系统管理介绍二、信息系统项目管理基础三、项目立项管理四、项目整体管理五、项目变更管理六、项目收尾管理七、项目范围管理八、项目进度管理九、项目成本管理十、项目质量管理十一、项目人力资源管理十二、项目沟通管…

Java的数据类型与变量详解

数据类型与变量 文章目录 数据类型与变量前言一、数据类型1. 基本数据类型2. 引用数据类型 二、包装类型1. 包装类型简介2. 自动装箱与拆箱3. 包装类型的常用方法4. 注意事项5. 示例 三、变量1. 变量声明2. 变量赋值3. 变量声明与赋值同时进行4. 示例 四、总结 前言 在Java编程…