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

news2024/9/21 20:37:37

今日内容

  • Leetcode. 491 递增子序列
  • Leetcode. 46 全排列
  • Leetcode. 47 全排列Ⅱ

Leetcode. 491 递增子序列

文章链接:代码随想录 (programmercarl.com)

题目链接:491. 非递减子序列 - 力扣(LeetCode)

本题也是一个子集问题,根据题意也知道要去重,提到去重就会不自觉地想到 90. 子集 II - 力扣(LeetCode)中的去重。但在本题中不能使用 Leetcode. 90 这种去重思想,因为这种去重需要对数组进行排序,而本题如果进行排序,会对得到的结果产生影响。

所以本题的去重应该用一个 Set 来记录本层已经使用过的元素。

根据上述内容,可写出代码:

class Solution {
    List<Integer> elem = new LinkedList<>();
    List<List<Integer>> result = new LinkedList<>();
    public List<List<Integer>> findSubsequences(int[] nums) {
        backtracking(nums, 0);
        return result;
    }
    public void backtracking(int[] nums, int startIndex){
        if (elem.size() >= 2){
            result.add(new LinkedList<>(elem));
        }
        if (startIndex == nums.length){
            return;
        }
        Set<Integer> used = new HashSet<>(); // 记录已使用元素的Set
        for (int i = startIndex; i < nums.length; i++){
            if (!elem.isEmpty() && nums[i] < elem.get(elem.size() - 1) || used.contains(nums[i])){continue;}
            used.add(nums[i]);
            elem.add(nums[i]);
            backtracking(nums, i + 1);
            elem.remove(elem.size() - 1);
        }
    }
}
  • 时间复杂度:O(n * 2 ^ n)
  • 空间复杂度:O(n)

Leetcode. 46 全排列

文章链接:代码随想录 (programmercarl.com)

题目链接:46. 全排列 - 力扣(LeetCode)

本题是回溯问题中的排列问题, 排列问题和组合问题不同,排列问题返回得结果是有序的,比如{1, 2} {2, 1} 在排列问题中是两个不同的结果。

也正因为结果有序,所以和组合问题、分割问题以及子集问题不同,排列问题每次搜索都要从头开始,所以不需要startIndex指示下一次搜索开始的位置。

虽然排列问题不需要startIndex了,但是它返回的结果是有序的,元素的排列顺序依然需要其他变量进行标识。因此需要使用一个数组来记录每个元素的使用情况

本题中,我们使用一个布尔数组 used 来标识每个元素的使用情况,当本层遍历使用到该元素后,该元素在used数组中的值被赋为 true。在遍历元素时,就可以根据 used 数组中对应索引的值来判断是否被使用,被使用就跳过。

排列问题经过抽象得到的树形结构图如下所示:

根据上述内容,写出如下代码:

class Solution {
    List<Integer> elem = new LinkedList<>();
    List<List<Integer>> result = new LinkedList<>();
    public List<List<Integer>> permute(int[] nums) {
        boolean[] used = new boolean[nums.length]; // 记录元素的使用情况
        backtracking(nums, used);
        return result;
    }
    public void backtracking(int[] nums, boolean[] used){
        if (elem.size() == nums.length){
            result.add(new LinkedList<>(elem));
            return;
        }
        for (int i = 0; i < nums.length; i++){
            if (used[i]){continue;} // 若元素已使用过,则跳过该元素
            elem.add(nums[i]);
            used[i] = true; // 元素被使用,赋值为true
            backtracking(nums, used);
            used[i] = false; // 回溯
            elem.remove(elem.size() - 1);  
        }
    }
}
  • 时间复杂度:O(n!)
  • 空间复杂度:O(n)

Leetcode. 47 全排列Ⅱ

文章链接:代码随想录 (programmercarl.com)

题目链接:47. 全排列 II - 力扣(LeetCode)

本题可以看作是 Leetcode. 46 + Leetcode. 90 的结合,也就是在全排列问题中加入去重。

代码如下:

class Solution {
    List<Integer> elem = new LinkedList<>();
    List<List<Integer>> result = new LinkedList<>();
    public List<List<Integer>> permuteUnique(int[] nums) {
        boolean[] used = new boolean[nums.length];
        Arrays.sort(nums); // 注意一定要排序
        backtracking(nums, used);
        return result;
    }
    public void backtracking(int[] nums, boolean[] used){
        if (elem.size() == nums.length){
            result.add(new LinkedList<>(elem));
            return;
        }
        for (int i = 0; i < nums.length; i++){
            if (i > 0 && nums[i] == nums[i - 1] && used[i - 1] == true){ // 判断元素是否被使用以及去重
                continue;
            }
            if (used[i]){continue;}
            elem.add(nums[i]);
            used[i] = true;
            backtracking(nums, used);
            used[i] = false;
            elem.remove(elem.size() - 1);
        }
    }
}
  • 时间复杂度:O(n! * n)
  • 空间复杂度:O(n)

总结

第一题是去重的不同,去重时注意所给数据是否有序,有序的话就可以使用 Leetcode. 90 的去重思想;无序的话就需要其他容器记录已使用元素。

排列问题要求结果有序,所以每次遍历都需要从头开始,并且需要一个容器记录哪些元素被使用过,注意这里的标识不是为了去重,而是为了调整结果顺序。

去重和判断元素使用情况的区别,从Leetcode. 47 就可以看出来了。

 

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

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

相关文章

【AI绘画】Midjourney后置指令--seed、--tile、--q、--chaos、--w、--no详解

博客主页&#xff1a; [小ᶻZ࿆] 本文专栏: AI绘画 | Midjourney 文章目录 &#x1f4af;前言&#x1f4af;Midjourney后置指令--seed测试1测试2如何获取未指定种子图片的随机种子注意点 &#x1f4af;Midjourney后置指令--tile测试 &#x1f4af;Midjourney后置指令--q(or-…

Retrieval-based-Voice-Conversion-WebUI模型构建指南

一、模型介绍 Retrieval-based-Voice-Conversion-WebUI&#xff08;简称 RVC&#xff09;模型是一个基于 VITS&#xff08;Variational Inference with adversarial learning for end-to-end Text-to-Speech&#xff09;的简单易用的语音转换框架。 具有以下特点 简单易用&a…

chrome浏览器如何设置自动播放音视频

使用场景&#xff1a; 有些场景需要打开页面后&#xff0c;自动播放视频或者视频流&#xff0c;这时候发现无法播放&#xff0c;打开浏览器控制台发现有下面的错误提示&#xff1a;NotAllowedError: play() failed because the user didnt interact with the document first 。…

顶级出图效果!免费在线使用FLux.1 模型,5s出图无限制!

最近发现一个可以在线免费使用 FLux.1 模型 生成图片的AI工具。 先看效果图&#xff1a; 工具不需要登录即可使用&#xff0c;目前还是完全免费的&#xff0c;国内可以直接使用。 在提示词输入框直接输入提示词即可&#xff0c;选择图片比例之后&#xff0c;直接生图。 出图的…

安全运营之浅谈SIEM告警疲劳

闲谈&#xff1a; 刚开始学习SIEM、态势感知这类产品的时&#xff0c;翻阅老外们的文章总是谈什么真阳性&#xff0c;假阳性告警、告警疲劳&#xff0c;当时在国内资料中没找到很合理的解释&#xff0c;慢慢就淡忘这件事了。随着慢慢深入工作&#xff0c;感觉大概理解了这些概念…

‌技术人必看!如何科学规划,从需求出发打造完美技术方案

引言 在互联网架构师的角色中&#xff0c;我们面临的挑战不仅仅是编写代码&#xff0c;更重要的是深入理解需求、设计系统&#xff0c;并确保我们的解决方案能够稳定、高效地运行。本文将详细介绍从新需求提出到技术方案发布的全过程。 1. 理解现有需求和场景 在开始一个新的…

信息学奥赛初赛天天练-87-NOIP2014普及组-完善程序-矩阵、子矩阵、最大子矩阵和、前缀和、打擂台求最大值

1 完善程序 最大子矩阵和 给出 m行 n列的整数矩阵&#xff0c;求最大的子矩阵和(子矩阵不能为空)。 输入第一行包含两个整数 m和 n&#xff0c;即矩阵的行数和列数。之后 m行&#xff0c;每行 n个整数&#xff0c;描述整个矩阵。程序最终输出最大的子矩阵和。 &#xff08;最…

SAP中mmpv自动过账—附带源码

想省事儿的直接拖到后面查看代码 思路分析 实现逻辑:初版 前台测试:选择屏幕确认公司代码。必要情况手动开账勾选前台执行按钮 1.1去marv表找公司代码的当前账期,简单运算获取下一个账期。1.2执行bdc,模拟前台手动开账期1.3执行的必要信息存日志表。例:修改人(开账期的人…

FastAPI 进阶:使用 BackgroundTasks 处理长时间运行的任务

在 FastAPI 中&#xff0c;BackgroundTasks 是一个功能&#xff0c;它允许你在发送响应给客户端之后执行后台任务。这些任务对于不需要客户端等待的操作非常有用&#xff0c;比如发送电子邮件通知或处理数据。然而&#xff0c;当服务器重启时&#xff0c;由于 BackgroundTasks …

C++: set与map容器的介绍与使用

本文索引 前言1. 二叉搜索树1.1 概念1.2 二叉搜索树操作1.2.1 查找与插入1.2.2 删除1.2.3 二叉搜索树实现代码 2. 树形结构的关联式容器2.1 set的介绍与使用2.1.1 set的构造函数2.1.2 set的迭代器2.1.3 set的容量2.1.4 set的修改操作 2.2 map的介绍与使用2.2.1 map的构造函数2.…

基于python的mediapipe姿态识别 动作识别 人体关健点 实现跳绳状态判别 计数功能

基于Python的MediaPipe姿态识别实现跳绳状态判别与计数功能 项目概述 本项目旨在利用Google的MediaPipe库&#xff0c;结合姿态识别技术&#xff0c;实现对跳绳动作的实时检测与计数功能。通过识别人体关键点&#xff0c;系统能够准确判断跳绳动作的状态&#xff0c;并实时统…

Java入门:07.Java中的面向对象03

11 this关键字 this关键字有两个作用 第一个作用&#xff0c;用来调用重载的构造方法 public class Test3{public static void main(String[] args){new User();new User("ls");new User("ls","女");} } ​ class User{String name ;String sex…

Autosar工程师必读:ETAS工具链自动化实战指南<三>

----自动化不仅是一种技术&#xff0c;更是一种思维方式&#xff0c;它将帮助我们在快节奏的工作环境中保持领先&#xff01; 目录 往期推荐 自动化命令--generate 命令语法 参数说明 命令使用前提 场景1&#xff1a;BSW代码生成 场景2&#xff1a;RTE代码生成 场景3&a…

对非洲33国免关税!非洲市场不容错过

2024年9月5日中非合作论坛峰会在北京隆重召开&#xff0c;会议后宣布对非洲33个国家实行0关税的优惠政策&#xff0c;并且在未来三年&#xff0c;推动中国企业对非投资不少于700亿元人民币。 自然而然的&#xff0c;中非友好关系必然会带动中国对非洲市场的出口&#xff0c;近…

云计算实训44——K8S及pod相关介绍

一、K8S基本概念 1、k8s是什么 K8S是Kubernetes的 缩写&#xff0c;由于k 和 s 之间有⼋个字符&#xff0c;所以因此得名。 Kubernetes 是⼀个可移植的、可扩展的开源平台&#xff0c;⽤于管理容器化 的⼯作负载和服务&#xff0c;可促进声 明式配置和⾃动化。 2、k8s的功能…

STM32F1+HAL库+FreeTOTS学习10——任务相关API函数使用

STM32F1HAL库FreeTOTS学习10——任务相关API函数使用 任务相关API函数1. uxTaskPriorityGet()2. vTaskPrioritySet()3. uxTaskGetNumberOfTasks()4. uxTaskGetSystemState()5. vTaskGetInfo()6. xTaskGetCurrentHandle()7. xTaskGetHandle()8. xTaskGetIdleTaskHandle()9. uxTa…

你需要掌握的算法:快慢指针

文章目录 前言龟兔赛跑乌龟能否追上兔子乌龟与兔子在何处相遇龟兔问题的推论 快慢指针基础概念发展历史 快慢指针的应用检测链表是否有环找到链表的中间节点计算链表的环长度找到链表环的入口节点 小结 前言 在处理链表数据结构时&#xff0c;快慢指针是一种非常高效的算法技巧…

鸡尾酒排序算法

目录 引言 一、概念 二、算法思想 三、图例解释 1.采用冒泡排序&#xff1a; 2.采用鸡尾酒排序&#xff1a; 3.对比总结 四、算法实现 1.代码实现 2.运行结果 3.代码解释 五、总结 引言 鸡尾酒排序&#xff08;Cocktail Sort&#xff09;&#xff0c;也被称为双向冒…

同一天!蚂蚁集团宣布将发布3款AI新产品!腾讯、零一万物、面壁智能推出最新大模型|AI日报

文章推荐 缓解父母焦虑&#xff01;详细实测&#xff01;这些免费AI可以成为孩子提高学习能力的得力助手&#xff01; 附送试听地址&#xff01;OpenAI ChatGPT被曝将新增8种语音&#xff01;英特尔酷睿Ultra 200V正式发布&#xff5c;AI日报 今日热点 蚂蚁将发布三款AI新产…

Zynq7020 SDK 初学篇(4)- PL 端 GPIO

1.开发背景 基于 PS 端 GPIO 的基础上&#xff0c;如何调用 PL 端 GPIO 的输入输出 2.开发需求 PL 端按键控制 PL 端 LED 3.开发环境 Zynq7020 Vivado2017.4 4.实现步骤 4.1 设计配置 这里设置 PIO 数量 3 个 由于 PL 端不像 PS 端一样绑定 GPIO&#xff0c;所以需要对上面…