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

文章目录

    • 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;
        }
    }
}

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

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

相关文章

数据结构——单链表专题

目录 1. 链表的概念及结构2. 实现单链表初始化尾插头插尾删头删查找在指定位置之前插入数据在指定位置之后插入数据删除指定位之前的节点删除指定位置之后pos节点销毁链表 3. 完整代码test.cSList.h 4. 链表的分类 1. 链表的概念及结构 在顺序表中存在一定的问题&#xff1a; …

15.一种坍缩式的简单——组合模式详解

当曾经的孩子们慢慢步入社会才知道&#xff0c;那年味渐淡的春节就像是疾驰在人生路上的暂停键。 它允许你在隆隆的鞭炮声中静下心来&#xff0c;瞻前顾后&#xff0c;怅然若失。 也允许你在寂静的街道上屏气凝神&#xff0c;倾听自己胸腔里的那团人声鼎沸。 孩子们会明白的&am…

库的操作【数据库】

目录 一、创建数据库 二、删除数据库 ​编辑 三、数据库编码问题 四、库的改查 查 1&#xff09;查有哪些数据库&#xff1a; 2&#xff09;使用某个数据库&#xff1a; 3&#xff09;当前在哪个数据库&#xff1a; 4&#xff09;有谁在使用 改alter 五、备份和恢复 …

Shiro-02-shiro 是什么?

序言 大家好&#xff0c;我是老马。 前面我们学习了 5 分钟入门 shiro 安全框架实战笔记&#xff0c;让大家对 shiro 有了一个最基本的认识。 shiro 还有其他优秀的特性&#xff0c;今天我们就一起来学习一下&#xff0c;为后续深入学习奠定基础。 Apache Shiro 是什么&…

2.18通过字符设备驱动分步注册过程实现LED驱动的编写,编写应用程序测试

应用程序&#xff1a; #include<stdlib.h> #include<stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include<unistd.h> #include<string.h> #include<sys/ioctl.h> #include"myled.h&quo…

LabVIEW智能家居控制系统

LabVIEW智能家居控制系统 介绍了一个基于LabVIEW的智能家居控制系统的开发过程。该系统利用LabVIEW软件与硬件设备相结合&#xff0c;通过无线网络技术实现家居环境的实时监控与控制&#xff0c;提升居住舒适度和能源使用效率。 项目背景&#xff1a;随着科技的发展和生活水平…

vue-router 实现路由懒加载

在现代的Web开发中&#xff0c;前端技术的发展日新月异。在构建大规模单页应用&#xff08;Single Page Application&#xff09;时&#xff0c;路由管理是一个非常重要的环节。随着用户对网页速度和性能的要求越来越高&#xff0c;有效的路由管理能够显著提升用户体验。本篇博…

【RT-DETR有效改进】利用EMAttention加深网络深度提高模型特征提取能力(特征选择模块)

一、本文介绍 本文给大家带来的改进机制是EMAttention注意力机制,它的核心思想是,重塑部分通道到批次维度,并将通道维度分组为多个子特征,以保留每个通道的信息并减少计算开销。EMA模块通过编码全局信息来重新校准每个并行分支中的通道权重,并通过跨维度交互来捕获像素级…

IT行业高含金量证书全解析:开启职业生涯新篇章

在快速发展的IT行业&#xff0c;持续学习和专业认证是提升个人竞争力的重要途径。全球范围内存在着众多的IT认证&#xff0c;它们不仅能够验证你的技术能力&#xff0c;还能在求职和职业晋升中起到关键作用。 本篇博客将深入探讨IT行业中部分高含金量的证书&#xff0c;包括中…

【IO流】IOException IO流异常

IOException IO流异常 1. 概述2. try...catch异常处理2.1 基础做法2.2 JDK7方案2.3 JDK9方案 3. 注意事项 异常 概括 1. 概述 IOException&#xff08;Input/Output Exception&#xff0c;输入/输出异常&#xff09;是 Java 编程中常见的异常类型之一。它是 java.io 包中定义的…

速看!2024年泰国国际电力能源展10月16-18日

2024年泰国&#xff08;亚洲&#xff09;国际电力能源展暨电工技术设备展 展会时间&#xff1a;2024年10月16-18日 展会地点&#xff1a;泰国.曼谷BITEC会展中心 主办单位&#xff1a;新加坡Fireworks展览集团 组织单位&#xff1a;武汉柏翰展览有限公司(Fireworks China) …

SQL Developer 小贴士:Unshared Worksheet

在Oracle SQL Developer中&#xff0c;最常用的功能应该是SQL Worksheet&#xff0c;或Worksheet。 可以创建两类Worksheet&#xff0c;即Worksheet和Unshared Worksheets。前者是共享数据库连接的&#xff0c;后者会单独创建自己的连接。前者的快捷键是AltF10&#xff1b;后者…

趋高技术开发出超低价的视觉尺寸测量仪软件

2024年1月1日元旦节当日&#xff0c;深圳市趋高技术有限公司Fuxi实验室开发组成员成功开发出一款视觉尺寸测量仪软件。这款软件类比市场价格处于超低价。仅报三千二百元。有需要的码农或客户都可以了解一下&#xff0c;带回家。 趋高技术HITREND是深圳的一家高科技公司。 …

阅读笔记(SOFT COMPUTING 2018)Seam elimination based on Curvelet for image stitching

参考文献&#xff1a; Wang Z, Yang Z. Seam elimination based on Curvelet for image stitching[J]. Soft Computing, 2018: 1-16. 注&#xff1a;SOFT COMPUTING 大类学科小类学科Top期刊综述期刊工程技术 3区 COMPUTER SCIENCE, ARTIFICIAL INTELLIGENCE 计算机&#xf…

【论文解读】Latency-Aware Collaborative Perception

Latency-Aware Collaborative Perception 摘要引言方法SystemSyncNet 实验 摘要 协作感知最近显示出提高单智能体感知感知能力的巨大潜力。现有的协同感知方法通常考虑理想的通信环境。然而&#xff0c;在实践中&#xff0c;通信系统不可避免地存在延迟问题&#xff0c;导致安…

IO进程线程第一天

1.完成注册登录功能&#xff1a; 做个小菜单&#xff0c;功能1&#xff1a;是注册功能&#xff0c;输入注册账户和注册密码&#xff0c;将账户和密码写入文件中 功能2&#xff1a;是登录功能&#xff0c;提示并输入登录账户和登录密码&#xff0c;并用其遍历文件中的每一组账户…

应用回归分析:岭回归

岭回归&#xff0c;也称为Tikhonov正则化&#xff0c;是一种专门用于处理多重共线性问题的回归分析技术。多重共线性是指模型中的自变量高度相关&#xff0c;这种高度的相关性会导致普通最小二乘法&#xff08;OLS&#xff09;估计的回归系数变得非常不稳定&#xff0c;甚至无法…

二维码的颜色怎么改变?轻松3步修改二维码样式

怎么修改二维码的颜色呢&#xff1f;一般我们制作的二维码或者经过系统生成的二维码大多都是黑白颜色的&#xff0c;有些小伙伴会觉得不太美观无法满足自己的使用需求。那么对于想要修改二维码样式的小伙伴&#xff0c;可以使用二维码生成器的二维码美化功能来处理&#xff0c;…

力扣 第 124 场双周赛 解题报告 | 珂学家 | 非常规区间合并

前言 整体评价 T4的dp解法没想到&#xff0c;走了一条"不归路", 这个区间合并解很特殊&#xff0c;它是带状态的&#xff0c;而且最终的正解也是基于WA的case&#xff0c;慢慢理清的。 真心不容易&#xff0c;太难了。 T1. 相同分数的最大操作数目 I 思路: 模拟 c…

【机构vip教程】Charles(1):Charles的介绍及安装

Charles Charles 是在 Mac &#xff08;Charles是跨平台的 &#xff09;下常用的网络封包截取工具&#xff0c;在做移动开发、测试时&#xff0c;我们为了调试与服务器端的网络通讯协议&#xff0c;常常需要截取网络封包来分析。Charles是一个HTTP代理服务器,HTTP监视器,反转代…