算法打卡day25|回溯法篇05|Leetcode 491.递增子序列、46.全排列、47.全排列 II

 算法题

Leetcode 491.递增子序列

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

大佬视频讲解:递增子序列视频讲解

 个人思路

和昨天的子集2有点像,但昨天的题是通过排序,再加一个标记数组来达到去重的目的。

而本题求自增子序列,是不能对原数组进行排序的,因为排完序的数组都是自增子序列了。解决这道题还是用回溯法解决.

解法
回溯法

把递增子序列问题抽象为如下树形结构

回溯法三部曲

1.递归函数参数

本题求子序列,很明显一个元素不能重复使用,所以需要startIndex,调整下一层递归的起始位置。再加上结果列表和路径

2.终止条件

本题其实类似求子集问题,也是要遍历树形结构找每一个节点,所以可以不加终止条件,startIndex每次都会加1并不会无限递归。但本题收集结果有所不同,题目要求递增子序列大小至少为2.

3.单层搜索逻辑

 在图中可以看出,同一父节点下的同层上使用过的元素就不能再使用了,再加上题目中说了,数值范围[-100,100],所以这里可以用HashSet来记录同层是否重复使用元素

class Solution {
    List<List<Integer>> result = new ArrayList<>();//结果列表
    List<Integer> path = new ArrayList<>();
    public List<List<Integer>> findSubsequences(int[] nums) {
        backTracking(nums, 0);
        return result;
    }
    private void backTracking(int[] nums, int startIndex){
        if(path.size() >= 2) result.add(new ArrayList<>(path)); //收集结果
           
        HashSet<Integer> hs = new HashSet<>();//标记重复使用的元素,避免同层重复取元素

        for(int i = startIndex; i < nums.length; i++){
            if(!path.isEmpty() && path.get(path.size() -1 ) > nums[i] || hs.contains(nums[i]))
                continue;
            hs.add(nums[i]);
            path.add(nums[i]);
            backTracking(nums, i + 1);
            path.remove(path.size() - 1);//回溯
        }
    }
}

时间复杂度:O(n * 2^n));(循环n个元素,2^n表示所有可能的子集数量)

空间复杂度:O(n);(递归栈的深度最多为 n)


 Leetcode  46.全排列

题目链接:46.全排列

大佬视频讲解:全排列视频讲解

个人思路

这是典型的全排列问题,只能用for循环暴力再加回溯法解决。

解法
回溯法

以[1,2,3]为例,抽象成树形结构如下

回溯法三部曲

1.递归函数参数

首先排列是有序的,也就是说 [1,2] 和 [2,1] 是两个集合,这和之前分析的子集以及组合所不同的地方。根据抽象出来的树形结构,可以看出元素1在[1,2]中已经使用过了,但是在[2,1]中还要在使用一次1,所以处理排列问题就不用使用startIndex了。但排列问题需要一个used数组,标记已经选择的元素. 再加上结果列表和路径

2.递归终止条件

可以看出叶子节点,就是收割结果的地方。也就是当收集元素的数组path的大小达到和nums数组一样大的时候,说明找到了一个全排列,也表示到达了叶子节点。

3.单层搜索的逻辑

这里for循环里不用startIndex了。因为排列问题,每次都要从头开始搜索,例如元素1在[1,2]中已经使用过了,但是在[2,1]中还要再使用一次1。而used数组,其实就是记录此时path里都有哪些元素使用了,一个排列里一个元素只能使用一次

class Solution {

    List<List<Integer>> result = new ArrayList<>();// 存放符合条件结果的集合
    LinkedList<Integer> path = new LinkedList<>();// 用来存放符合条件结果
    boolean[] used;

    public List<List<Integer>> permute(int[] nums) {
        if (nums.length == 0){
            return result;
        }
        used = new boolean[nums.length];//初始化
        permuteHelper(nums);
        return result;
    }

    private void permuteHelper(int[] nums){
        if (path.size() == nums.length){//终止条件,收集叶子节点
            result.add(new ArrayList<>(path));
            return;
        }
        for (int i = 0; i < nums.length; i++){
            if (used[i]){//一个排列里一个元素只能使用一次
                continue;
            }
            used[i] = true;
            path.add(nums[i]);
            permuteHelper(nums);
            path.removeLast();//回溯
            used[i] = false;//回溯
        }
    }
}

时间复杂度:O(n!);(全排列)

空间复杂度:O(n);(递归栈的深度最多为 n)


 Leetcode  47.全排列 II

题目链接:47.全排列 II

大佬视频讲解:全排列 II视频讲解

 个人思路

这题和上题区别在与给定一个可包含重复数字的序列,要返回所有不重复的全排列。所以这里又涉及到去重了,依旧是树层不能重复取,树枝可以重复取

解法
回溯法

把 [1,1,2],抽象为如下树形结构

这道题的去重逻辑和 Leetcode  40.组合总和II 一样,搞清楚同一树层去重就能解决这道题。

这里注意一点:对于排列问题,树层上去重和树枝上去重,都是可以的,但是树层上去重效率更高!

class Solution {
    
    List<List<Integer>> result = new ArrayList<>();//存放结果
    List<Integer> path = new ArrayList<>();//暂存结果

    public List<List<Integer>> permuteUnique(int[] nums) {
        boolean[] used = new boolean[nums.length];
        Arrays.fill(used, false);//初始化

        Arrays.sort(nums);//排序 以方便去重
        backTrack(nums, used);
        return result;
    }

    private void backTrack(int[] nums, boolean[] used) {
        if (path.size() == nums.length) {
            result.add(new ArrayList<>(path));
            return;
        }
        for (int i = 0; i < nums.length; i++) {
            // used[i - 1] == true,说明同⼀树⽀nums[i - 1]使⽤过
            // used[i - 1] == false,说明同⼀树层nums[i - 1]使⽤过

            // 如果同⼀树层nums[i - 1]使⽤过则直接跳过
            if (i > 0 && nums[i] == nums[i - 1] && used[i - 1] == false) {
                continue;
            }

            //如果同⼀树⽀nums[i]没使⽤过开始处理
            if (used[i] == false) {
                used[i] = true;//标记同⼀树⽀nums[i]使⽤过,防止同一树枝重复使用
                path.add(nums[i]);
                backTrack(nums, used);
                path.remove(path.size() - 1);//回溯,说明同⼀树层nums[i]使⽤过,防止下一树层重复
                used[i] = false;//回溯
            }
        }
    }
}

时间复杂度:O(n! * n);(全排列*可重复的元素)

空间复杂度:O(n);(递归栈的深度最多为 n)


 以上是个人的思考反思与总结,若只想根据系列题刷,参考卡哥的网址代码随想录算法官网

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

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

相关文章

springboot检测脚本

import requests import urllib3 urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) session requests.session()# 从文本文件中读取 with open(dic.txt, r) as file:paths file.readlines()# 移除每个末尾的换行符 paths [path.strip() for path in pa…

线程创建方式、构造方法和线程属性

欢迎各位&#xff01;&#xff01;&#xff01;推荐PC端观看 文章重点&#xff1a;学会五种线程的创造方式 目录 1.开启线程的五种方式 2.线程的构造方法 3.线程的属性及获取方法 1.开启线程的五种方式 创造线程的基本两步&#xff1a;&#xff08;1&#xff09;使用run方法…

并发编程之Callable方法的详细解析(带小案例)

Callable &#xff08;第三种线程实现方式&#xff09; Callable与Runnable的区别 Callable与Runnable的区别 实现方法名称不一样 有返回值 抛出了异常 ​class Thread1 implements Runnable{Overridepublic void run() { ​} } ​ class Thread2 implements Callable<…

x86的内存分段机制

8086 是 Intel 公司第一款 16 位处理器&#xff0c;诞生于 1978 年&#xff0c;所以说它很古老。 一.8086 的通用寄存器 8086 处理器内部共有 8 个 16 位的通用处理器&#xff0c;分别被命名为 AX、 BX、 CX、 DX、 SI、 DI、 BP、 SP。如下图所示。 “通用”的意思是…

【JavaSE】String类详解

目录 前言 1. 什么是String类 1.1 String的构造 1.2 String类的基本操作&#xff1a;打印、拼接、求字符串长度 2. String类的常用方法 2.1 字符串查找 2.2 字符串替换 2.3 字符串拆分 2.4 字符串截取 2.5 字符串和其他类型的转换 2.6 去除字符串左右两边的空格 3.…

日赚2000万的短剧,还能火多久?

沈瑶初十年前就义无反顾地爱上高禹川&#xff0c;当他们两人再次相遇&#xff0c;她主动靠近高禹川&#xff0c;不料&#xff0c;她却意外怀孕&#xff0c;高禹川为了负责选择领证&#xff0c;但不公布两人的关系...... 这是一部情绪稳定女航医与傲娇疯批男机长的虐恋剧。在这个…

【MongoDB】一问带你深入理解什么是MongDB,MongoDB超超详细保姆级教程

目录 1、MongoDB概述2、MongoDB 主要特点2.1、文档2.2、集合2.3、数据库2.4、数据模型 3、Windows安装MongoDB3.1、下载MongoDB3.2、安装MongoDB3.3、配置MongoDB 4、Linux安装MongoDB4.1、下载MongoDB4.2、解压安装4.3、安装一个可视化工具 5、MongoDB基本操作及增删改查5.1、…

【案例·增】获取当前时间、日期(含,SQL中DATE数据类型)

问题描述&#xff1a; 需要使用当前时间、日期&#xff0c;可以使用 SQL 中的 CURDATE() 、NOW()、CURTIME()运算符 案例&#xff1a; INSERT INTO table_name(current_time, column_name2,...) VALUES (NOW(),, ...)规则(Date 相关函数)&#xff1a; 规则(Date数据类型)

构建一个包含mvn命令的Java 17基础镜像

前言 官方提供的openjdk基础镜像&#xff0c;不包含mvn命令&#xff0c;无法用容器来打包代码。 在官方提供的镜像基础上安装maven。 前期准备&#xff0c;需要安装好docker。 一、安装maven 1、下载openjdk基础镜像&#xff0c;执行如下代码。 docker pull openjdk:17-j…

19. 变量

文章目录 一、变量二、变量的定义格式 一、变量 变量&#xff1a;程序中临时存储数据的容器&#xff0c;在程序执行过程中&#xff0c;其值有可能发生改变的量&#xff08;数据&#xff09;。但是这个容器中只能存一个值。 应用场景&#xff1a;在我们登录页面的时候&#xf…

JavaSE day14笔记

第十四天课堂笔记 课上: 适当做笔记课下 : 总结 , 读代码 , 反复敲代码 , 做练习 数组★★★ 数组 : 存储多个 同一类型 的容器格式 :数组类型 : 引用数据类型, new运算符在堆中 分配一块连续的存储空间 , 系统会给数组元素默认初始化 , 将该数组的引用赋值给数组名 引用数据…

3月28号总结

java学习 1.this关键字 this关键字可以代表当前对象的引用。它可以在类的方法中使用&#xff0c;用于引用调用该方法的对象。通过this关键字&#xff0c;可以访问类的成员变量和方法&#xff0c;以及调用其他构造函数。 举一个实例来学习一下this关键字的作用。 比如&#…

【unity】如何汉化unity Hub

相信大家下载安装unity后看着满操作栏的英文&#xff0c;英文不好的小伙伴们会一头雾水。但是没关系你要记住你要怎么高速运转的机器进入中国&#xff0c;请记住我给出的原理&#xff0c;不懂不代表不会用啊。现在我们就来把编译器给进行汉化。 第一步&#xff1a;我们打开Uni…

QT控件之显示控件

Qt Designer显示窗口部件提供的面板中&#xff0c;提供了10种显示小部件 &#xff08;1&#xff09; Label标签 &#xff08;2&#xff09; Text Browser文本浏览器 &#xff08;3&#xff09; Graphics View图形视图 &#xff08;4&#xff09; Calendar Widget日历 &…

IU5507低功耗DC-DC降压稳压器

IU5507T是一款由基准电压源、振荡电路、比较器、PWM/PFM 控制电路等构成的 CMOS 降压DC/DC调整器。利用 PWM/PFM 自动切换控制电路达到可调占空比&#xff0c;具有全输入电压范围(3-18V)内的低纹波、高效率和大输出电流等特点。 IU5507T内置功率MOSFET&#xff0c;使用过压、过…

libVLC 捕获鼠标、键盘事件

在实现播放器的时候&#xff0c;我们需要捕获键盘、鼠标事件进行视频快进、快退&#xff0c;或者双击全屏/退出全屏窗口、鼠标右键弹出菜单栏。默认情况下&#xff0c;在使用libVLC库的时候&#xff0c;我们无法捕获这些事件&#xff0c;因为我们将Qt的视频窗口传递给了libVLC。…

损坏的RAID5csp

1.解题思路 这道题太抽象了&#xff0c;一开始都没太搞懂在讲啥。。。解决该题需要了解条带、磁盘号的定义。 下图以样例2&#xff0c;输入编号为5的块为例&#xff1a; 请务必加上ios::sync_with_stdio(false),否则会超时只有30分 2.满分代码 #include<iostream> us…

Hbase 王者荣耀数据表 HBase常用Shell命令

大数据课本&#xff1a; HBase常用Shell命令 在使用具体的Shell命令操作HBase数据之前&#xff0c;需要首先启动Hadoop&#xff0c;然后再启动HBase&#xff0c;并且启动HBase Shell&#xff0c;进入Shell命令提示符状态&#xff0c;具体命令如下&#xff1a; $ cd /usr/local…

Hello算法2:复杂度分析

Hello算法2&#xff1a;复杂度分析 本文是基于k神的Hello 算法的读书笔记&#xff0c;请支持实体书。 https://www.hello-algo.com/chapter_paperbook/ 算法效率 算法效率评估 设计算法时&#xff0c;我们追求以下两个目标&#xff1a; 找出解法找出最优解 最优解通常包含…

Douyin视频详情数据API接口(视频详情,评论)

抖音官方并没有直接提供公开的视频详情数据采集API接口给普通用户或第三方开发者。抖音的数据采集通常受到严格的限制&#xff0c;以保护用户隐私和平台安全。 请求示例&#xff0c;API接口接入Anzexi58 如果您需要获取抖音视频详情数据&#xff0c;包括评论、点赞等&#xff…