代码随想录刷题笔记 DAY 29 | 非递减子序列 No.491 | 全排列 No.46 | 全排列 II No. 47

news2025/3/10 17:55:37

文章目录

    • Day 29
      • 01. 非递减子序列(No. 491)
        • 1.1 题目
        • 1.2 笔记
        • 1.3 代码
      • 02. 全排列(No. 46)
        • 2.1 题目
        • 2.2 笔记
        • 2.3 代码
      • 03. 全排列 II(No. 47)
        • 3.1 题目
        • 3.2 笔记
        • 3.3 代码

Day 29

01. 非递减子序列(No. 491)

题目链接

代码随想录题解

1.1 题目

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

看完题目,很容易就可以发现,递增子序列就是 符合递增条件的子集,而且其中会包含重复元素,这就和昨天做到的题目 子集 II 十分相似,建议做完这道题再来看本题的题解

代码随想录刷题笔记 DAY 28 | 复原 IP 地址 No.93 | 子集 No.78 | 子集 II No.90

但是有一个很大的坑:

递增子序列是无法通过排序来去重的

回顾一下子集中如果出现重复的元素的去重方式

[1 2 2] ,将这个数组进行排序如果一层中遇到相同的元素就进行 continue

但递增子序列的问题就是它的顺序是固定的,不能通过排序来去重。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

比如说如上的这种情况,所有的节点都会去遍历相同的子树,这就导致了重复。

所以要做的是 层内去重,但是又不能通过排序的方式,所以我们可以想到在每一层去声明一个 record 当发现后续遍历的内容已经在 record 中出现的时候就跳过本次遍历。

这个 record 可以采用哈希方式实现,也可以使用列表方式去实现,显然哈希的实现方式更好

    public void backtracking(int index, int[] nums) {
        if (index > nums.length - 1) {
            return;
        }
        int[] record = new int[300];
        for (int i = index; i < nums.length; i++) {
            // 去重操作
            if (i > index && record[nums[i]+100] > 0) {
                continue;
            } else {
                record[nums[i] + 100] = 1;
            }
           // ...
        }
    }

因为 nums[i] 的范围是在 -100100 的范围内的,所以这里将 nums[i] + 100 存入数组,避免出现越界的情况。

这样就完成了层内的去重,剩下的就是考虑如何保证递增了。

显然这里也有两种选择:

  • 写一个方法,每次去判断 path 是否符合
  • 在递归过程中去判断

先来看比较容易理解的第一个方法

 public boolean isValid(List<Integer> path) {
        if (path.size() <= 1) {
            return false;
        }
        int currentMax = Integer.MIN_VALUE;
        for (int i : path) {
            if(i < currentMax) {
                return false;
            } else {
                currentMax = i;
            }
        }
        return true;
}

判断一个列表是否非递减,只需要在递增中不断更新 currentMax 并且确定后面的元素是否大于等于这个 current 即可。

在递归中也是相同的思路,只需要判断 nums[i] 是否大于等于 path.get(size() - 1) 也就是最后一个元素即可,否则,同样 continue

    if (!path.isEmpty() && nums[i] < path.get(path.size() - 1)) {
    	continue;
    } else {
    	record[nums[i] + 100] = 1;
    }

将这段代码和上面去重的代码组成一个 if 语句,写出代码。

1.3 代码
class Solution {
    List<Integer> path = new ArrayList<>();
    List<List<Integer>> res = new ArrayList<>();
    public List<List<Integer>> findSubsequences(int[] nums) {
        backtracking(0, nums);
        return res;
    }
    public void backtracking(int index, int[] nums) {
        if (index > nums.length - 1) {
            return;
        }
        int[] record = new int[300];
        for (int i = index; i < nums.length; i++) {
            // 去重操作
            if (i > index && record[nums[i]+100] > 0 ||
                !path.isEmpty() && nums[i] < path.get(path.size() - 1)) {
                continue;
            } else {
                record[nums[i] + 100] = 1;
            }
            path.add(nums[i]);
            if (path.size() > 1) {
                res.add(new ArrayList(path));
            }
            backtracking(i+1, nums);
            path.remove(path.size() - 1);
        }
    }
}

02. 全排列(No. 46)

题目链接

代码随想录题解

2.1 题目

给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。

示例 1:

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

示例 2:

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

示例 3:

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

提示:

  • 1 <= nums.length <= 6
  • -10 <= nums[i] <= 10
  • nums 中的所有整数 互不相同
2.2 笔记

上面说到过,回溯法可以解决排列问题,这就是一个经典的例子。

当遇到一开始思路不明确的回溯的题,建议大家先把树形结构画出来,这样各种操作就一目了然了。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

遍历到 1 之后就只能遍历 23 了,也就是每次遍历到一个节点,在这个节点剩余的遍历过程中,这个节点的值都不能出现,即在数组中删除掉这个遍历过的数。

但在数组中删除的操作时间复杂度相当高,所以很明显需要用到标记数组的方法。

与上题区分开,这里使用 boolean 数组

因为这里的去重是在路径中的,对全局的去重,所以标记数组的声明需要在层外

    boolean[] used;
    public List<List<Integer>> permute(int[] nums) {
        used = new boolean[30];
        // ...
    }
	public void backtracking(int[] nums) {
        // ...
    }

当路径中遇到遍历过的内容的时候就跳过

		for (int i = 0; i < nums.length; i++) {
            if (used[nums[i] + 10]) {
                continue;
            }
			// ...
        }

如果大家做过一些回溯的题目,很容易发现当层内去重的时候就不需要回溯,而路径去重就需要回溯,因为层内去重是在一层 for 循环中做的。

递归的终点,很显然就是当收集的数量等于数组长度的时候。

        if (path.size() == nums.length) {
            res.add(new ArrayList(path));
            return;
        }

写出代码

2.3 代码
class Solution {
    List<Integer> path = new ArrayList<>();
    List<List<Integer>> res = new ArrayList<>();
    boolean[] used;
    public List<List<Integer>> permute(int[] nums) {
        used = new boolean[30];
        backtracking(nums);
        return res;
    }
    public void backtracking(int[] nums) {
        if (path.size() == nums.length) {
            res.add(new ArrayList(path));
            return;
        }
        for (int i = 0; i < nums.length; i++) {
            if (used[nums[i] + 10]) {
                continue;
            }
            path.add(nums[i]);
            used[nums[i] + 10] = true;
            backtracking(nums);
            path.remove(path.size() - 1);
            used[nums[i] + 10] = false;
        }
    }
}

03. 全排列 II(No. 47)

题目链接

代码随想录题解

3.1 题目

给定一个可包含重复数字的序列 nums按任意顺序 返回所有不重复的全排列。

示例 1:

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

示例 2:

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

提示:

  • 1 <= nums.length <= 8
  • -10 <= nums[i] <= 10
3.2 笔记

做过上一题的朋友不用猜也能知道这个题要考察的是什么

就是在数组中加上重复的元素,考察层内去重的问题

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

所以这道题除了上题的路径去重还需要添加上层内去重。

但路径去重的时候应该注意,不能再以 nums[i] 作为标识了,因为内部含有相同的元素,所以应该使用 i 下标作为去重的标识。

		for (int i = 0; i < nums.length; i++) {
            if (used[i]) {
                continue;
            }
			// ...
        }

然后只需要加上层内去重的代码就大功告成了

本题几乎没有新的内容,只需要注意路径去重的逻辑即可。

3.3 代码
class Solution {
    List<Integer> path = new ArrayList<>();
    List<List<Integer>> res = new ArrayList<>();
    boolean[] used;
    public List<List<Integer>> permute(int[] nums) {
        used = new boolean[30];
        backtracking(nums);
        return res;
    }
    public void backtracking(int[] nums) {
        if (path.size() == nums.length) {
            res.add(new ArrayList(path));
            return;
        }
        for (int i = 0; i < nums.length; i++) {
            if (used[nums[i] + 10]) {
                continue;
            }
            path.add(nums[i]);
            used[nums[i] + 10] = true;
            backtracking(nums);
            path.remove(path.size() - 1);
            used[nums[i] + 10] = false;
        }
    }
}

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

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

相关文章

Spring Boot打war包部署到Tomcat,访问页面404 !!!

水善利万物而不争&#xff0c;处众人之所恶&#xff0c;故几于道&#x1f4a6; 文章目录 Spring Boot打war包部署到Tomcat&#xff0c;访问页面404 &#xff01;&#xff01;&#xff01;解决办法&#xff1a;检查Tomcat版本和Jdk的对应关系&#xff0c;我的Tomcat是6.x&#x…

C语言系列-预定义符号#define定义宏#define定义宏

&#x1f308;个人主页: 会编辑的果子君 &#x1f4ab;个人格言:“成为自己未来的主人~” 目录 预定义符号 #define定义常量 #define定义宏 预定义符号 C语言设置了一些预定义符号&#xff0c;可以直接使用&#xff0c;预定义符号也是在预处理期间处理的。 __FILE__ /…

渗透测试练习题解析 4(CTF web)

1、[GXYCTF2019]禁止套娃 1 考点&#xff1a;git 泄露 进入靶场后只有一串文字&#xff0c;源代码、抓包之类的都没有敏感信息出现&#xff0c;直接用 kali 的 dirsearch 扫描 发现存在 .git 目录&#xff0c;猜测应该是源码泄露&#xff0c;使用 GitHack 扒一下源码&#xff0…

第13章 网络 Page747~749 asio核心类 ip::tcp::resolver

3&#xff0c; ip::tcp::resolver 如果新浪的IP地址变了&#xff0c;该怎么办呢? ip::tcp::resolver 可以帮我们用上www.sina.com.cn&#xff0c;因为它负责将人类可读的多种网址信息&#xff0c;一步 到位地解析成ip::tcp::socket建立连接所需要的ip::tcp::endpoint结构&…

【FastAPI】P1 安装与第一个 FastAPI 应用

目录 FastAPI 安装第一个 FastAPI 应用代码拆解分析 FastAPI 安装 FastAPI 是用于快速构建 API 的 web 框架&#xff0c;依赖 Python 3.8 及更高版本。使用 pip 命令安装 fastapi&#xff1a; pip install fastapi安装异步处理 ASGI 的服务器 Uvicorn&#xff1a; pip insta…

pipx — 在隔离环境中安装和运行 Python 应用程序

pipx官网&#xff1a; https://pipx.pypa.io/stable/ pipx pipx 是一个用于安装和运行Python应用程序的工具&#xff0c;它类似于 Linux的 apt 和JavaScript 的 npx 。 pipx和pip的区别&#xff1a; pip是一个通用的python包安装工具pipx专注于安装python cli程序 cli&#…

Web 扫描神器:WhatWeb 保姆级教程(附链接)

一、介绍 WhatWeb 是一款用于识别网站技术栈和特征的开源Web扫描工具。它可以自动分析网站的响应并识别出使用的Web框架、CMS、服务器、JavaScript库等技术组件。WhatWeb的目标是通过分析网站的内容&#xff0c;提供有关目标的技术信息&#xff0c;这对于安全测试、漏洞评估和…

移动云云桌面应用场景广泛,助力行政、教育等领域的办公转型

当今办公场景&#xff0c;远程办公和视频会议逐渐常态化&#xff0c;但是在实际应用过程中都需要PC设备的支持&#xff0c;当然还有很多其他的场景也是如此。为了满足使用要求&#xff0c;我们走到哪里就需要把设备带到哪里&#xff0c;非常不方便。那么&#xff0c;有没有一种…

javaSpringbootmysql大学生综合素质测评系统65290-计算机毕业设计项目选题推荐(附源码)

摘 要 本论文主要论述了如何使用java语言开发一个Springboot大学生综合素质测评系统&#xff0c;本系统将严格按照软件开发流程进行各个阶段的工作&#xff0c;采用B/S架构&#xff0c;面向对象编程思想进行项目开发。本文将论述大学生综合素质测评系统的当前背景以及系统开发的…

代码随想录算法训练营第54天 | 123.买卖股票的最佳时机III + 188.买卖股票的最佳时机IV

今日任务 123.买卖股票的最佳时机III 188.买卖股票的最佳时机IV 123.买卖股票的最佳时机III - Hard 题目链接&#xff1a;力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 给定一个数组&#xff0c;它的第 i 个元素是一支给定的股票在第 i 天的价格。…

【详解】图的概念和存储结构(邻接矩阵,邻接表)

目录 图的基本概念&#xff1a; 图的存储结构 邻接矩阵&#xff08;GraphByMatrix&#xff09;&#xff1a; 基本参数&#xff1a; 初始化&#xff1a; 获取顶点元素在其数组中的下标 &#xff1a; 添加边和权重&#xff1a; 获取顶点的度&#xff1a; 打印图&#xf…

前端vue金额用逗号分隔

实现效果 代码 template部分 <el-input v-model"state.val"></el-input><div>{{ priceFor(state.val) }}</div> js部分 const state reactive({ val: });const priceFor (val)> {if(!val){return }else if(val.length<4){return…

LDM:High-Resolution Image Synthesis with Latent Diffusion Models

LDM: High-Resolution Image Synthesis with Latent Diffusion Models TL; DR&#xff1a;关键的技术点有两个。一是通过感知压缩将 Diffusion 从像素空间的转换到隐空间来做&#xff0c;降低训练/采样的算力成本&#xff0c;提高生成质量。二是通过交叉注意力&#xff0c;将各…

统计平台项目总体架构设计方案

1 总体规划 1.1 设计原则 按照本项目的建设目标,结合本项目具有涉及范围广、建设规模大、数据构成复杂等特点,在设计阶段需遵循一些重要原则,以保障后续建设的顺利衔接和有效执行。 1、规范性 系统设计开发遵循通用的国际规范及各系统间接口标准,保障中台基础信息数据库…

0205-2-数据链路层

第 3 章 数据链路层 使用点对点信道的数据链路层 数据链路和帧 数据链路层使用的信道主要有以下两种类型&#xff1a; 点对点信道。这种信道使用一对一的点对点通信方式。广播信道。这种信道使用一对多的广播通信方式&#xff0c;因此过程比较复杂。广播信道上连接的主机很多…

JAVA并发编程之ConcurrentHashMap详解

ConcurrentHashMap 一、ConcurrentHashMap写入数据流程 一般在项目中使用ConcurrentHashMap时&#xff0c;都是作为JVM缓存使用的。 ConcurrentHashMap是线程安全的。如果你项目涉及到了多个线程都会操作key-value结构时&#xff0c;别用HashMap&#xff0c;一定要上Concurr…

【Java多线程】线程中几个常见的属性以及状态

目录 Thread的几个常见属性 1、Id 2、Name名称 3、State状态 4、Priority优先级 5、Daemon后台线程 6、Alive存活 Thread的几个常见属性 1、Id ID 是线程的唯一标识&#xff0c;由系统自动分配&#xff0c;不同线程不会重复。 2、Name名称 用户定义的名称。该名称在各种…

Shellcode免杀对抗(Python)

Shellcode Python免杀&#xff0c;绕过360安全卫士、火绒安全、Defender Python基于cs/msf的上线 cs 执行代码2种可供选择 执行代码 1&#xff1a; rwxpage ctypes.windll.kernel32.VirtualAlloc(0, len(shellcode), 0x1000, 0x40) ctypes.windll.kernel32.RtlMoveMemory…

线程安全性的原理分析学习

初步认识Volatile 一段代码引发的思考 下面这段代码&#xff0c;演示了一个使用volatile以及没使用volatile这个关键字&#xff0c;对于变量更新的影响 package com.sp.demo;/*** author : lssffy* Description :* date : 2024/2/16 18:42*/ public class VolatileDemo {publi…

阿里云香港轻量应用服务器是什么线路?cn2?

阿里云香港轻量应用服务器是什么线路&#xff1f;不是cn2。 阿里云香港轻量服务器是cn2吗&#xff1f;香港轻量服务器不是cn2。阿腾云atengyun.com正好有一台阿里云轻量应用服务器&#xff0c;通过mtr traceroute测试了一下&#xff0c;最后一跳是202.97开头的ip&#xff0c;1…