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

目录

题目链接:491.递增子序列

思路

代码

题目链接:46.全排列

思路

代码

题目链接:47.全排列 II

思路

代码

总结


题目链接:491.递增子序列

思路

        求递增子序列,其实也是求子集的一种,只是添加了限定条件。首先,子序列中元素的个数大于等于2,其次是保证递增,最后不能有重复的子序列。

        元素个数可以比较path中元素个数来保证;递增可以通过对比当前要收集的元素与path中第一个元素对比来保证;最后一点,去重,之前做的题去重都是对数组进行了排序,但是这道题对顺序有要求,不能重排数组,所以使用set把遍历过的元素存进去,如果发现当前遍历的元素已经遍历过了,则不收集结果,继续循环。

代码

class Solution {
public:
    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> uset; // 存每层遍历过的元素,用来去重
        for (int i = startindex; i < nums.size(); i++) {
            // path非空,并且当前元素大于path中第一个元素
            // 或者在uset中出现过当前元素
            // 满足上述条件,则不进行结果收集
            if (!path.empty() && nums[i] < path.back() ||
                uset.find(nums[i]) != uset.end()) {
                continue;
            }
            path.push_back(nums[i]);   // 将当前元素存进path
            uset.insert(nums[i]);      // 存进uset
            backtracking(nums, i + 1); // 递归
            path.pop_back();           // 回溯
        }
        return;
    }

    vector<vector<int>> findSubsequences(vector<int>& nums) {
        backtracking(nums, 0);
        return result;
    }
};

题目链接:46.全排列

思路

        排列与组合不同的是,排列中要包含所有元素,而且只要排列顺序不同,就是不同的排列结果。因此根据这两个特点来写回溯代码。

        在结果收集上,是在叶子节点进行收集,当path元素个数等于nums元素个数时进行结果收集

        因为排列中要包含所有元素,所以每一层遍历都要遍历整个数组,但是为了避免收集已经使用过的元素,使用bool型的used数组。每加入一个元素将其对应的used置1,如果当前元素已经加入到了path中,不收集当前元素,继续循环。

代码

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++) {
            // 使用used数组来避免取到重复元素
            if (used[i] == true) {
                continue;
            }
            path.push_back(nums[i]);  // 存进path
            used[i] = true;           // used置1
            backtracking(nums, used); // 递归
            path.pop_back();          // 回溯
            used[i] = false;          // used置0
        }
        return;
    }
    vector<vector<int>> permute(vector<int>& nums) {
        vector<bool> used(nums.size(), false);
        backtracking(nums, used);
        return result;
    }
};

题目链接:47.全排列 II

思路

        与46.全排列不同的是数组中有重复元素,所以只需对上述代码进行更改,加入去重的操作即可。这里的去重与之前数组中有重复元素的组合类似,只进行树层去重,所以上述代码中的used数组有了第二个作用,树层去重。

        对数组进行排序后,当前元素与上一个元素相等,并且上一个元素的used为false,这就说明,该进行树层去重了,当前元素所收集的结果,在遍历上一个元素时已经收集过了,所以跳过当前元素。

        如果当前元素与上一个元素相等,但是上一个元素的used为true,这说明这两个元素不在同一树层,或者说当前元素所在树层比上一个元素深一层,所以可以进行结果收集,例如[2,1,1]这种情况。

代码

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++) {
            // used作用有两个
            // 一是为了避免加入排列内元素重复
            // 二是为了树层去重
            // 去重,与之前的组合类似
            // 当前元素与上一个元素相等,并且上一个元素还为加入path中
            // 说明这是树枝的开始,直接舍弃
            if (i > 0 && nums[i] == nums[i - 1] && used[i - 1] == false) {
                continue;
            }
            // 当前元素还未加入path中,所以可以进行节点处理
            if (used[i] == false) {
                path.push_back(nums[i]); // 节点处理
                used[i] = true;
                backtracking(nums, used); // 递归
                path.pop_back();          // 回溯
                used[i] = false;
            }
        }
    }
    vector<vector<int>> permuteUnique(vector<int>& nums) {
        vector<bool> used(nums.size(), false);
        sort(nums.begin(), nums.end()); // 对数组排序,用于去重
        backtracking(nums, used);
        return result;
    }
};

总结

        ①递增子序列也是组合问题的一种,只是加了一些限定条件,所以在原先回溯代码的模板上将限定条件加上即可

        ②排列问题,排列中包含所有元素,顺序不同即结果不同,最后结果不能有重复排列。由于结果要求包含所有元素,所以每次都要对整个数组进行遍历,为了防止有重复元素加入,使用bool 型的used数组记录使用过的元素

        ③数组中有重复元素时,去重思路与之前的组合问题类似,先对数组进行排序,然后利用used数组进行树层去重

        ④目前接触到的使用回溯算法的问题,大体上都是同一个思路,只是要将不同问题的限定条件体现在框架当中

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

网络协议——IS-IS协议详解

1. IS-IS是什么 IS-IS是一种基于链路状态并使用最短路径优先算法进行路由计算的一种IGP协议。IS-IS属于内部网关协议&#xff0c;用于自治系统内部。IS-IS是一种链路状态协议&#xff0c;使用最短路径优先算法进行路由计算。 2. 应用场景&#xff08;园区网和骨干网&#xff0…

冯诺依曼与进程【Linux】

文章目录 冯诺依曼体系结构&#xff08;从硬件的角度描述&#xff09;冯诺依曼体系结构&#xff08;从软件的角度描述&#xff09;操作系统&#xff08;软件&#xff09;理解管理系统调用和库函数进程查看进程的两种方式 通过系统调用获取进程的PID和PPID通过系统调用创建进程-…

RAG学习笔记系列(一)

RAG 介绍 RAG 全称为 Retrieval Augmented Generation&#xff08;检索增强生成&#xff09;。是基于LLM构建系统的一种架构。 RAG 基本上可以理解为&#xff1a;搜索 LLM prompting。根据用户的查询语句&#xff0c;系统会先使用搜索算法获取到相关内容作为上下文&#xff0…

IMU应用于膝关节功能评估

近日&#xff0c;来自中国的研究团队开发了一款基于IMU的可穿戴系统&#xff0c;用于评估膝关节骨关节炎引发的功能障碍。研究着重重验证该系统在测量步态及下肢功能方面的准确性&#xff0c;通过对比业界公认的运动捕捉和步态分析系统&#xff0c;评估IMU传感器在这一领域的性…

Compose 简单组件

文章目录 Compose 简单组件TextText属性使用AnnotatedStringSpanStyleParagraphStyle SelectionContainer 和 DisableSelectionClickableText TextFieldTextField属性使用OutlinedTextFieldBasicTextFieldKeyboardOptions 键盘属性KeyboardActions IME动作 ButtonButton属性使用…

Python 数据结构和算法实用指南(三)

原文&#xff1a;zh.annas-archive.org/md5/66ae3d5970b9b38c5ad770b42fec806d 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 第七章&#xff1a;哈希和符号表 我们之前已经看过数组和列表&#xff0c;其中项目按顺序存储并通过索引号访问。索引号对计算机来说很有效…

Docker+Uwsgi+Nginx部署Django项目保姆式教程

之前&#xff0c;我和大家分享了在docker中使用uwsgi部署django项目的教程。这次&#xff0c;为大家带来的是使用DockerUwsgiNginx部署Django项目。废话不多说&#xff0c;我们开干。 步骤1&#xff1a;使用命令创建一个django项目 我这里python版本使用的是3.9.x 首先&#…

有爱有乐有知识,还有《米小圈上学记》!

“读万卷书&#xff0c;不如行万里路”&#xff0c;说的是读再多的书&#xff0c;也比不上走过万水千山所得。可是又有几人能得尝山水之妙&#xff0c;大多被困于尘世中。我虽走过一些山水&#xff0c;但大多因生存困于一隅&#xff0c;不得随心而行。 然而&#xff0c;读书也…

nmon进行性能资源监控

一、前言 在工作中可能会遇到需要在压测的时候对Linux服务器进行性能资源监控的情况。这时可以用nmon来对服务器进行监控。 二、nmon的下载安装 1.查看系统信息 cat /etc/os-release 结果为 PRETTY_NAME"Debian GNU/Linux 12 (bookworm)"NAME"Debian GNU/…

不用Linux也可以的强大文本处理方法

不用Linux也可以的强大文本处理方法 标题党了&#xff0c;其实是论VIM的使用。 做生物信息分析最合适的还是Linux操作系统&#xff0c;所以生信宝典在最开始就推出了Linux学习系列&#xff0c;由浅入深的讲述了Linux学习中的关键点。 主要文章列举如下&#xff1a; Linux学…

代码随想录算法训练营DAY25|C++回溯算法Part.2|216. 组合总和II、17.电话号码的字母组合

文章目录 216. 组合总和II题意理解树形结构伪代码实现剪枝操作CPP代码实现 17.电话号码的字母组合解题思路树形结构伪代码实现隐藏回溯CPP代码 216. 组合总和II 力扣题目链接 文章讲解&#xff1a;216. 组合总和III 视频讲解&#xff1a;和组合问题有啥区别&#xff1f;回溯算法…

python复制文件夹内容

参考博客 https://blog.csdn.net/itfans123/article/details/133710731 案例1 import os import shutildef copy_folder(source_folder, destination_folder):# 创建目标文件夹os.makedirs(destination_folder, exist_okTrue)# 遍历源文件夹中的所有文件和文件夹for item in …

【简单讲解下如何用爬虫玩转石墨文档】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…

力扣算法-回溯

递归 104.二叉树的最大深度 回溯 17.电话号码的字母组合 ①子集型回溯 78.子集 (1)选不选 (2)选哪个 131.分割回文串 &#xff08;1593.拆分字符串使唯一子字符串的数目最大 也可以用这个思路解&#xff1a;从结果角度&#xff0c;分割字符串&#xff09; ②组合型回溯…

【C++】哈希二

上篇博客我们写了解决哈希冲突的两种办法&#xff0c;不过我们写的都是针对整形的&#xff0c;而在实际情况下&#xff0c;要存入哈希表中的数据可以是string或自定义类型等等。那么我们就应该想一种办法去解决这里的问题。 比如说string&#xff0c;我们想到如何让string也转为…

代码随想录算法练习Day11:链表相交

题目&#xff1a;给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点&#xff0c;返回 null 。 题目链接&#xff1a;160.链表相交 题目思路&#xff1a;定义两个指针&#xff0c;分别遍历两链表&#xff0c;如…

后端获取请求体Body,将请求体进行解密放回Request请求,并能通过@RequestBody获取

目前系统发送的post和put请求都是没有加密数据。客户需要将请求体加密。而系统已经基本开发完成&#xff0c;不可能一个一个去修改发送的请求。就需要在发送请求时候在拦截器中将body进行加密。并且在后端进行请求过滤解密&#xff0c;并且能通过RequestBody继续获取对象。 1.…

RuoYi-Cloud部署实战(手动部署)

RuoYi-Cloud部署实战 语雀 1. 若依源码和架构 RuoYi-Cloud: &#x1f389; 基于Spring Boot、Spring Cloud & Alibaba的分布式微服务架构权限管理系统&#xff0c;同时提供了 Vue3 的版本 若依项目结构 带端口号的是需要启动的服务 com.ruoyi ├── ruoyi-ui …

各大厂都推出鸿蒙APP了,你就一定要学习一下鸿蒙APP测试了!

2023年8月&#xff0c;华为推出鸿蒙4.0&#xff0c;由于其广泛的用户基础和品牌传播力&#xff0c;在短短几个月的时间&#xff0c;使用鸿蒙4.0系统的设备就达到千万级别&#xff0c;并且在9月份发售Mate 6之后&#xff0c;还在装机量的增长更加迅猛。 基于此&#xff0c;11月…

德立电子授权世强先进代理分销,加速车规级磁性元器件产品拓展

为提供先进、可靠的磁性元件产品&#xff0c;世强先进&#xff08;深圳&#xff09;科技有限公司与惠州市德立电子有限公司&#xff08;下称“德立电子”&#xff0c;英文名&#xff1a;DDY&#xff09; 签署授权代理合作协议&#xff0c;旨在为汽车电子、工业、消费、通信、医…
最新文章