回溯算法去重的两种写法

回溯算法去重的两种写法

关于回溯,无论是排列、组合、子集,都会涉及到两个问题,一个是去重,另一个则是剪枝;

去重通常有几种方法。

以这道题来做验证。

90.子集II

力扣题目链接(opens new window)

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

说明:解集不能包含重复的子集。

示例:

  • 输入: [1,2,2]
  • 输出: [ [2], [1], [1,2,2], [2,2], [1,2], [] ]

used数组

用一个全局变化的used数组来记录是否重,used[0] == true即代表用过了。

这里要进行

  • 是需要去统一树枝的重还是同一层高度的重

  • 去重之前应该进行哪些工作?

  • 怎么样判断去重

首先去重之前必定先排列

原因是更加方便的去重,因为排列后相同的元素会相邻,这样就有利于去重的判断

其次通过一张图可以回答第一个问题(图引用自《代码随想录》

可以清晰看到,去重去的应该是同一层的树枝。

剩下则是去重的工作如何进行了。

同时上面那张图已经做了解答

在nums[i] == nums[i-1]的情况下,used[i-1] == false则是同一树层元素相同。

如果是used[i-1] == true,则是同一树枝元素相同。

代码

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

set去重

set去重则是利用了数据结构本身的特点。即不需要再去做判断,只需判断当前元素是否已经存在即可。

重点是set数组应该怎么样初始化?

  • 全局变量
  • 在for循环一层前

很明显,如果是全局变量,set数组记录的则是全部树枝的元素记录

这和我们之前得出的结论不同,我们应该要去掉同一层树枝的重。

因此只有在for循环每一层前初始化才能实现。

代码如下

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

h_back(nums[i]);
backtracking(nums,used,i+1);
path.pop_back();

    }
}

};


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

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

相关文章

【数据结构】树状数组总结

知识概览 树状数组有两个作用&#xff1a; 快速求前缀和 时间复杂度O(log(n))修改某一个数 时间复杂度O(log(n)) 例题展示 1. 单点修改&#xff0c;区间查询 题目链接 活动 - AcWing本活动组织刷《算法竞赛进阶指南》&#xff0c;系统学习各种编程算法。主要面向…

JavaSE第7篇:封装

文章目录 前言一、封装1、好处:2、使用 二、四种权限修饰符三、构造器1、作用2、说明3、属性赋值的过程 四 、JavaBean的使用五、UML类图六 、Java关键字1、this说明2 、this可以用来修饰属性、方法3、 this调用构造器 前言 不管学什么都可以按3w: what? why? how?&#xf…

AttributeError: module ‘jax‘ has no attribute ‘Array‘解决方案

大家好&#xff0c;我是爱编程的喵喵。双985硕士毕业&#xff0c;现担任全栈工程师一职&#xff0c;热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。…

NET模式和桥接模式简要概述

NET模式 NAT是Network Address Translation的缩写&#xff0c;即网络地址转换。NAT模式也是VMware创建虚拟机的默认网络连接模式。在NAT模式中&#xff0c;让虚拟机借助NAT功能&#xff0c;通过宿主机器所在的网络来访问公网。这里的宿主机相当于有两个网卡&#xff0c;一个是…

【FPGA】电梯楼层显示(简易)

前言 这是作者室友的项目&#xff0c;本来不管作者事儿的&#xff0c;但是后来听到说是室友去网上找人花了80块买了个劣质的&#xff0c;不仅是从CSDN上抄的&#xff0c;而且使用的板子还不符合室友的要求。可叹作者心软啊&#xff0c;顺便给室友做了。 在代码实现部分会给出设…

【学习笔记】V8垃圾回收策略

V8 V8是一款主流的JavaScript执行引擎V8采用即时编译,速度比较快V8内存设限,64位操作系统中上限为1.5G,32位系统中不超过800M V8垃圾回收策略 采用分代回收的思想内存分为新生代\老生代针对不同对象采用不同算法 v8常用的GC算法: 分代回收、空间复制、标记清除、标记整理、…

RDD编程

目录 一、RDD编程基础 &#xff08;一&#xff09;RDD创建 &#xff08;二&#xff09;RDD操作 1、转换操作 2、行动操作 3、惰性机制 &#xff08;三&#xff09;持久化 &#xff08;四&#xff09;分区 &#xff08;五&#xff09;一个综合实例 二、键值对RDD &am…

系列九、事务

一、事务 1.1、概述 事务是一组操作的集合&#xff0c;它是一个不可分割的工作单位&#xff0c;事务会把所有的操作作为一个整体一起向系统提交或者撤销操作请求&#xff0c;即&#xff1a;这些操作要么同时成功&#xff0c;要么同时失败。 例如: 张三给李四转账1000块钱&…

C语言短路操作

C语言短路操作 目录 一&#xff0e; 概述二&#xff0e; 例题 一&#xff0e; 概述 C语言中常用的短路操作符有两个&#xff0c;即逻辑与&#xff08;&&&#xff09;和逻辑或&#xff08;||&#xff09;。   对于逻辑与&#xff08;&&&#xff09;操作符&…

TCP/IP详解——FTP 协议,Telnet协议

文章目录 1. FTP 协议1.1 FTP的应用1.2 FTP传输文件的过程1.3 FTP传输模式1.4 主动模式&#xff08;Active Mode&#xff09;1.5 Active Mode 抓包分析1.6 被动模式&#xff08;Passive Mode&#xff09;1.7 Passive Mode 抓包分析 2. Telnet 协议2.1 Telnet 概念2.2 Telnet 协…

Golang清晰代码指南

发挥易读和易维护软件的好处 - 第一部分 嗨&#xff0c;开发者们&#xff0c;清晰的代码是指编写易于阅读、理解和维护的软件代码。它是遵循一组原则和实践&#xff0c;优先考虑清晰性、简单性和一致性的代码。清晰的代码旨在使代码库更易管理&#xff0c;减少引入错误的可能性…

python读取excel数据 附实战代码

在Python中&#xff0c;可以使用pandas库来读取Excel文件中的数据。下面是一个简单的例子&#xff1a; import pandas as pd# 读取Excel文件 df pd.read_excel(example.xlsx)# 显示前5行数据 print(df.head())在上面的代码中&#xff0c;我们首先导入了pandas库&#xff0c;并…

C/C++常见面试知识总结(三)

C语言是一种通用计算机&#xff08;高级&#xff09;编程语言&#xff1b;面向过程&#xff1b;广泛应用于计算机系统设计以及应用程序编写&#xff1b;设计目标&#xff0c;是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行…

springcloud微服务篇--5.Nacos注册中心

目录 一、认识Nacos 二、集成nacos 1.1添加依赖 1.2 注释掉order-service和user-service中原有的eureka依赖。&#xff08;避免冲突&#xff09; 1.3 注释eureka之后&#xff0c;添加nacos的客户端依赖&#xff1a; 三、服务注册到nacos 1、修改配置文件 2、启动并测试 四…

【网络安全】网络防护之旅 - Java安全机制探秘与数字证书引爆网络防线

&#x1f308;个人主页&#xff1a;Sarapines Programmer&#x1f525; 系列专栏&#xff1a;《网络安全之道 | 数字征程》⏰墨香寄清辞&#xff1a;千里传信如电光&#xff0c;密码奥妙似仙方。 挑战黑暗剑拔弩张&#xff0c;网络战场誓守长。 目录 &#x1f608;1. 初识网络安…

RTOS中任务的创建与删除

我们在stm32f103c8t6单片机上验证RTOS中任务的创建与删除&#xff0c;利用stm32cube进行RTOS的配置。在选择TIM2当做RTOS的时钟&#xff0c;裸机的时钟源默认是 SysTick&#xff0c;但是开启 FreeRTOS 后&#xff0c;FreeRTOS会占用 SysTick &#xff08;用来生成1ms 定时&…

camera曝光时间

曝光和传感器读数 相机上的图像采集过程由两个不同的部分组成。第一部分是曝光。曝光完成后&#xff0c;第二步就是从传感器的寄存器中读取数据并传输&#xff08;readout&#xff09;。 曝光&#xff1a;曝光是图像传感器进行感光的一个过程&#xff0c;相机曝光时间&#xf…

JWT令牌的作用和生成

JWT令牌&#xff08;JSON Web Token&#xff09;是一种用于身份验证和授权的安全令牌。它由三部分组成&#xff1a;头部、载荷和签名。 JWT令牌的作用如下&#xff1a; 身份验证&#xff1a;JWT令牌可以验证用户身份。当用户登录后&#xff0c;服务器会生成一个JWT令牌并返回…

Python实验项目9 :网络爬虫与自动化

实验 1&#xff1a;爬取网页中的数据。 要求&#xff1a;使用 urllib 库和 requests 库分别爬取 http://www.sohu.com 首页的前 360 个字节的数据。 # 要求&#xff1a;使用 urllib 库和 requests 库分别爬取 http://www.sohu.com 首页的前 360 个字节的数据。 import urllib.r…

当心字符串连接的性能

在Java中&#xff0c;字符串连接的性能问题同样需要注意&#xff0c;尤其是在循环中进行大量连接操作时。Java中的字符串是不可变的&#xff0c;因此每次连接字符串都会产生一个新的字符串对象&#xff0c;可能导致性能下降。以下是一些示例&#xff0c;演示了不同方法的字符串…