力扣日记2.22-【回溯算法篇】47. 全排列 II

news/发布时间2024/5/14 16:18:00

力扣日记:【回溯算法篇】47. 全排列 II

日期:2023.2.22
参考:代码随想录、力扣

47. 全排列 II

题目描述

难度:中等

给定一个可包含重复数字的序列 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

题解

cppver
class Solution {
public:
#define SOLUTION 2vector<int> path;vector<vector<int>> result;vector<vector<int>> permuteUnique(vector<int>& nums) {// 排序sort(nums.begin(), nums.end());vector<bool> used(nums.size(), false);backtracking(nums, used);return result;}
#if SOLUTION == 1void backtracking(vector<int>& nums, vector<bool>& used) {  // 因为存在重复值,所以不宜用哈希表记录是否使用过// 终止条件if (path.size() == nums.size()) {result.push_back(path);return;}int lastNum = -11;// for 横向遍历for (int i = 0; i < nums.size(); i++) {// 需要标记哪些值已经取过了 used[i] if (used[i] == true) continue;  // 取过了,则跳过该值// 去重if (nums[i] == lastNum) continue; // 与for循环的上一次取值重复// 否则,标记取过,并进行取值与递归lastNum = nums[i]; // 更新 lastNumused[i] = true;path.push_back(nums[i]);backtracking(nums, used);path.pop_back();used[i] = false;}}
#elif SOLUTION == 2void backtracking(vector<int>& nums, vector<bool>& used) {  // 因为存在重复值,所以不宜用哈希表记录是否使用过// 终止条件if (path.size() == nums.size()) {result.push_back(path);return;}// 使用 nums[i] == nums[i-1] 结合 used[i-1] 来判断是树枝重复还是树层重复// 树层重复的条件为:i > 0 && nums[i] == nums[i-1] && used[i-1] == false (上一个位置的元素未使用,说明是树层)// 树枝重复的条件为:i > 0 && nums[i] == nums[i-1] && used[i-1] == true// for 横向遍历for (int i = 0; i < nums.size(); i++) {// 树枝(纵向递归):标记哪些值已经取过了 used[i] if (used[i] == true) continue;  // 取过了,则跳过该值// 树层(用于去重)if (i > 0 && nums[i] == nums[i-1] && used[i-1] == false) continue; // 与for循环的上一次取值重复// 否则,标记取过,并进行取值与递归used[i] = true;path.push_back(nums[i]);backtracking(nums, used);path.pop_back();used[i] = false;}}
#endif
};

复杂度

  • 时间复杂度: O(n! * n)
  • 空间复杂度: O(n)

思路总结

  • 本题与 46. 全排列 的区别在于,集合中可能存在重复元素。因此,需要考虑去重,即在46题的基础上,需要在for循环遍历(横向遍历)中,过滤掉相同的元素(但又不能影响到纵向递归时元素的可重复选取)。
  • 不同于 40.组合总和 II 和 90.子集 II,全排列在for循环遍历时不能使用startindex,即每次for循环遍历都会从头开始遍历,不能直接在for循环中,用 if (i > 0 && nums[i] == nums[i-1]) continue; 来跳过重复元素,因为这样会使得在纵向递归时也无法选取到重复元素。
  • 因此,需要一个只会影响到横向遍历的变量,即代码中在for循环前定义的lastNum(这样每次for循环前会重置lastNum),用来记录相同层中for循环上次取到的元素——如果当前值与for循环上次取到的值相同,则跳过当前元素。且只有在该值也满足“纵向递归中当前位置未取过”的条件(used[i] == false)才会更新该lastNum(即当前值能进行取值、递归才会更新)。
  • 注意:
    • 去重 要提前做好排序
    • 由于本题存在重复元素,所以不能使用按值大小记录是否取过的哈希表作为used,而要使用按位置记录的usedvector<bool> used(nums.size(), false))。
    • 去重与是否使用过的if-continue判断条件的前后位置不影响(也可以写在一起),但取值、更新、递归、回溯等(所谓处理节点)一定要放在两者后面。
  • 树形结构示意图:
    • 在这里插入图片描述
  • 代码随想录版本:
    • 使用 nums[i] == nums[i-1] 结合 used[i-1] 来判断是树枝重复还是树层重复
      • 树层重复的条件为:i > 0 && nums[i] == nums[i-1] && used[i-1] == false (上一个位置的元素未使用,说明是树层)
      • 树枝重复的条件为:i > 0 && nums[i] == nums[i-1] && used[i-1] == true
      • 如图
      • 在这里插入图片描述
    • 所以在for循环中
      • 第一个条件用于排列取值
        // 树枝(纵向递归):标记哪些值已经取过了 used[i] 
        if (used[i] == true) continue;  // 取过了,则跳过该值
        
      • 第二个条件用于树枝去重
        if (i > 0 && nums[i] == nums[i-1] && used[i-1] == false) continue;
        

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

如若内容造成侵权/违法违规/事实不符,请联系编程老四网进行投诉反馈email:xxxxxxxx@qq.com,一经查实,立即删除!

相关文章

【Android安全】Windows 环境下载 Android 源码

准备环境 安装 git 安装 Python 硬盘剩余容量最好大于 100G 打开 Git Bash&#xff0c;用 git 克隆源代码仓库 git clone https://android.googlesource.com/platform/manifest.git //没有梯子使用清华源 git clone https://aosp.tuna.tsinghua.edu.cn/platform/manifest.git…

AutoTimes:通过大语言模型的自回归时间序列预测器

论文标题&#xff1a; AutoTimes: Autoregressive Time Series Forecasters via Large Language Models 作者&#xff1a;Yong Liu, Guo Qin, Xiangdong Huang, Jianmin Wang, Mingsheng Long 链接&#xff1a;https://arxiv.org/abs/2402.02370 机构&#xff1a;清华大学 …

【NTN 卫星通信】基于NTN和TN的Inter-PLMN海事应用场景

1 场景概述 NTN和TN联合组网的场景&#xff0c;可以有多种应用方式&#xff0c;以下用例描述了同时使用多个卫星PLMN和一个地面5G PLMN的海事场景。 MNO-G是一家成熟的卫星PLMN运营商&#xff0c;运营着几颗GEO卫星。MNO-L是一个相对较新的卫星PLMN运营商&#xff0c;操作LEO卫…

挑战30天学完Python:Day16 日期时间

&#x1f4d8; Day 16 &#x1f389; 本系列为Python基础学习&#xff0c;原稿来源于 30-Days-Of-Python 英文项目&#xff0c;大奇主要是对其本地化翻译、逐条验证和补充&#xff0c;想通过30天完成正儿八经的系统化实践。此系列适合零基础同学&#xff0c;或仅了解Python一点…

Android 输入法框架简介

每种平台都有自己的输入法框架. GNU/Linux 桌面环境有多种输入法框架, 比如 ibus, fcitx 等. 但是 Android 操作系统只有一种, 是统一提供的输入法框架. 相关链接: 《ibus 源代码阅读 (1)》 https://blog.csdn.net/secext2022/article/details/136099328https://developer.and…

【大厂AI课学习笔记NO.51】2.3深度学习开发任务实例(4)计算机视觉实际应用的特点

今天考试通过腾讯云人工智能从业者TCA级别的认证了&#xff01; 还是很开心的&#xff0c;也看不到什么更好的方向&#xff0c;把一切能利用的时间用来学习&#xff0c;总是对的。 我把自己考试通过的学习笔记&#xff0c;都分享到这里了&#xff0c;另外还有一个比较全的思维…

跨越千年医学对话:用AI技术解锁中医古籍知识,构建能够精准问答的智能语言模型,成就专业级古籍解读助手(LLAMA)

跨越千年医学对话&#xff1a;用AI技术解锁中医古籍知识&#xff0c;构建能够精准问答的智能语言模型&#xff0c;成就专业级古籍解读助手&#xff08;LLAMA&#xff09;。 介绍&#xff1a;首先在 Ziya-LLaMA-13B-V1基线模型的基础上加入中医教材、中医各类网站数据等语料库&a…

【爬虫逆向实战篇】定位加密参数、断点调试与JS代码分析

文章目录 1. 写在前面2. 确认加密参数3. 加密参数定位4. XHR断点调试 【作者主页】&#xff1a;吴秋霖 【作者介绍】&#xff1a;Python领域优质创作者、阿里云博客专家、华为云享专家。长期致力于Python与爬虫领域研究与开发工作&#xff01; 【作者推荐】&#xff1a;对JS逆向…

爬取m3u8视频

网址&#xff1a;https://www.bhlsm.com/cupfoxplay/609-3-1/ 相关代码&#xff1a; #采集网址&#xff1a;https://www.bhlsm.com/cupfoxplay/609-3-1/ #正常视频网站&#xff1a;完整视频内容 # pip install pycryptodomex #流媒体文件&#xff1a;M3U8&#xff08;把完整的…

React18源码: React调度中的3种优先级类型和Lane的位运算

优先级类型 React内部对于优先级的管理&#xff0c;贯穿运作流程的4个阶段&#xff08;从输入到输出&#xff09;&#xff0c;根据其功能的不同&#xff0c;可以分为3种类型&#xff1a; 1 &#xff09;fiber优先级(LanePriority) 位于 react-reconciler包&#xff0c;也就是L…

[ROS 系列学习教程] rosbag 命令行介绍

ROS 系列学习教程(总目录) 本文目录 rosbag 命令行1.1 rosbag check1.2 rosbag compress1.3 rosbag decompress1.4 rosbag filter1.5 rosbag fix1.6 rosbag info1.7 rosbag play1.8 rosbag record1.9 rosbag reindex 有时我们需要将 topic 中的数据保存下来以便后面分析&#x…

西门子S7-1500作为智能设备共享功能

本章节介绍了共享设备的功能&#xff0c;优势&#xff0c;使用要求&#xff0c;使用规则&#xff0c;如何将智能设备作为共享设备&#xff0c;实现一个智能设备同时与2个IO控制器进行通信的示例&#xff0c;以及常见问题。 一、共享设备功能概述 信号模块可以被不同的IO控制器…

SpringMVC 学习(三)之 @RequestMapping 注解

目录 1 RequestMapping 注解介绍 2 RequestMapping 注解的位置 3 RequestMapping 注解的 value 属性 4 RequestMapping 注解的 method 属性 5 RequestMapping 注解的 params 属性&#xff08;了解&#xff09; 6 RequestMapping 注解的 headers 属性&#xff08;了解&…

Linux环境下基本指令

今天我们一起来认识一下Linux环境下一些基本的指令&#xff0c;这些指令是我们学习Linux的基础&#xff0c;只有掌握了这些指令&#xff0c;我们才能在Linux环境下进一步学习知识&#xff0c;话不多说&#xff0c;我们开始&#xff08;以下演示操作是在云服务器的环境下&#x…

k8s-hpa控制器 16

hpa可通过metrics-server所提供pod的cpu或者内存的负载情况&#xff0c;从而动态拉伸控制器的副本数&#xff0c;从而达到后端的自动弹缩 官网&#xff1a;https://kubernetes.io/zh/docs/tasks/run-application/horizontal-pod-autoscalewalkthrough/ 上传镜像 创建hpa实例 …

【初始RabbitMQ】发布订阅的实现

发布确认原理 生产者将信道设置成 confirm 模式&#xff0c;一旦信道进入 confirm 模式&#xff0c;所有在该信道上面发布的消息都将会被指派一个唯一的 ID(从 1 开始)&#xff0c;一旦消息被投递到所有匹配的队列之后&#xff0c;broker 就会发送一个确认给生产者(包含消息的…

C语言每日一题(60)对链表进行插入排序

题目链接 力扣网 147 对链表进行插入排序 题目描述 给定单个链表的头 head &#xff0c;使用 插入排序 对链表进行排序&#xff0c;并返回 排序后链表的头 。 插入排序 算法的步骤: 插入排序是迭代的&#xff0c;每次只移动一个元素&#xff0c;直到所有元素可以形成一个有…

Puppeteer 使用实战:如何将自己的 CSDN 专栏文章导出并用于 Hexo 博客(二)

文章目录 上一篇效果演示Puppeteer 修改浏览器的默认下载位置控制并发数错误重试并发控制 错误重试源码 上一篇 Puppeteer 使用实战&#xff1a;如何将自己的 CSDN 专栏文章导出并用于 Hexo 博客&#xff08;一&#xff09; 效果演示 上一篇实现了一些基本功能&#xff0c;…

Python初学者必备:超级全面的基础知识详解

1. 数据类型和变量 Python使用缩进来组织代码块,一般使用4个空格的缩进.使用#来注释一行,其他每一行都是一个语句,当语句以冒号:结尾时,缩进的语句视为代码块.Python对大小写敏感. 1.1 整数 Python可以处理任意大小的整数,包括负整数,写法与数学上写法一致,例如&#xff1a;-…

联想开天昭阳N4620Z笔记本如何恢复出厂麒麟操作系统(图解)

联想开天昭阳N4620Z笔记本简单参数&#xff1a; 中央处理器&#xff1a;KX-6640MA G2 内存&#xff1a;8GB 固态硬盘&#xff1a;512GB SSD 显示器&#xff1a;14.0”FHD 电池&#xff1a;4Cell 操作系统&#xff1a;麒麟KOS中文RTM&#xff08;试用版&#xff09; 此款笔…
推荐文章