当前位置: 首页 > news >正文

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

力扣日记:【回溯算法篇】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;
        

相关文章:

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

力扣日记&#xff1a;【回溯算法篇】47. 全排列 II 日期&#xff1a;2023.2.22 参考&#xff1a;代码随想录、力扣 47. 全排列 II 题目描述 难度&#xff1a;中等 给定一个可包含重复数字的序列 nums &#xff0c;按任意顺序 返回所有不重复的全排列。 示例 1&#xff1a; 输…...

如何理解三大微分中值定理

文章看原文,自己写的只是备份 高等数学强化2:一元函数微分学 中值定理 极值点 拐点_一元函数中值定理-CSDN博客 高等数学强化3:一元函数积分学 P积分-CSDN博客 高等数学强化3:定积分几何应用-CSDN博客...

Linux--自定义shell

shell shell就是操作系统提供给用户与操作系统进行交互的命令行界面。它可以理解为一个用户与操作系统之间的接口&#xff0c;用户可以通过输入命令来执行各种操作&#xff0c;如文件管理、进程控制、软件安装等。Shell还可以通过脚本编程实现自动化任务。 常见的Unix系统中使…...

AIGC 实战:Ollama 和 Hugging Face 是什么关系?

Ollama和 Hugging Face 之间存在着双重关系&#xff1a; 1. Ollama是 Hugging Face 开发并托管的工具&#xff1a; Ollama是一个由 Hugging Face 自行开发的开源项目。它主要用于在本地运行大型语言模型 (LLM)&#xff0c;特别是存储在 GPT 生成的统一格式 (GPT-Generated Un…...

Gitee教程2(完整流程)

1.配置git git config --global user.name "用户名" git config --global user.email "密码" 如何获取&#xff1f; gitee右上角加号点击新建仓库&#xff0c;仓库名随便起一个就行 找到这条命令&#xff0c;把这两句一个一个复制到vscode终端就行 2.创建g…...

Go 1.22 中的 for 循环新特性详解

目录 每次迭代都创建新变量 支持整数类型循环 小结 在 Go 语言中&#xff0c;for 循环是实现迭代的主要方式。Go 中的 for 循环非常灵活&#xff0c;有多种使用方式&#xff0c;包括传统的三部分 for 循环、类似于其他语言中的 while 循环以及迭代集合的 range 循环。 在 1…...

igolang学习2,golang开发配置国内镜像

go env -w GO111MODULEon go env -w GOPROXYhttps://goproxy.cn,direct...

R语言空间分析、模拟预测与可视化

随着地理信息系统&#xff08;GIS&#xff09;和大尺度研究的发展&#xff0c;空间数据的管理、统计与制图变得越来越重要。R语言在数据分析、挖掘和可视化中发挥着重要的作用&#xff0c;其中在空间分析方面扮演着重要角色&#xff0c;与空间相关的包的数量也达到130多个。在本…...

体育赛事直播系统软件开发

体育赛事直播系统的软件开发是一个复杂的项目&#xff0c;需要多个方面的准备和工作。以下是开发这样一个系统可能涉及的主要步骤和考虑因素&#xff1a; 需求分析和规划&#xff1a;首先需要明确系统的功能需求&#xff0c;包括直播视频的流媒体处理、用户管理、直播赛事安排…...

使用 kind 集群安装运行极狐GitLab Runner【上】

GitLab 是一个全球知名的一体化 DevOps 平台&#xff0c;很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab 是 GitLab 在中国的发行版&#xff0c;专门为中国程序员服务。可以一键式部署极狐GitLab。 关于 kind kind 是一个用来运行本地 Kubernetes 机群的工具&a…...

wine 源码 vk3d wine-gecko wine-mono 各版本 国内下载地址 中国科技技术大学源

下载地址 Index of /wine/...

【ArcGIS微课1000例】0104:二位面状数据转三维多面体(建筑物按高度拉伸)

文章目录 一、加载数据二、添加高度字段三、三维拉伸显示四、生成三维体数据五、注意事项一、加载数据 打开ArcScene,加载配套实验数据(0104.rar中的二维建筑物矢量数据,订阅专栏,获取专栏所有文章阅读权限及配套数据),如下图所示: 二、添加高度字段 本实验将二维数据…...

jquery简介与解析

jQuery是一款流行的JavaScript库&#xff0c;旨在简化客户端脚本编写。它针对DOM操作、事件处理、动画效果和AJAX交互提供了简洁高效的解决方案&#xff0c;使得开发者能够更加便捷地创建交互式网页。 // jQuery小插件&#xff1a;给带有highlight类的元素添加鼠标悬停效果 (fu…...

Apache Commons开源的工具库介绍

Apache Commons 是 Apache 软件基金会主持的一个项目&#xff0c;旨在提供一系列可重用的 Java 组件。这些组件覆盖了从数据封装、文本处理到网络通信等各个方面&#xff0c;是 Java 开发中常用的一系列工具库。Apache Commons 项目下的各个库通常以 "commons-" 开头…...

SQL语法法则

概念 SQL语法规则&#xff1a;SQL是一种结构化编程语言 基础SQL指令通常是以行为单位 SQL指令需要语句结束待&#xff0c;默认是英文分号:;、\g、\G SQL指令类似自然语言 编写的SQL中如果用到了关键字或者保留字&#xff0c;需要使用反引号、来包裹&#xff0c;让系统忽略 …...

Java命令模式:让请求成为对象

Java命令模式&#xff1a;让请求成为对象 在软件设计中&#xff0c;我们经常遇到需要将操作或请求封装成对象的情况。这样&#xff0c;我们可以将它们作为参数传递、排队、记录或撤销。命令模式正是为了满足这种需求而诞生的。在命令模式中&#xff0c;一个请求或操作被封装成…...

研究生摆烂摆烂的一个寒假

寒假&#xff1a;27-24&#xff0c;不到一个月 刚回家&#xff0c;不想学习&#xff0c;摆烂 想学了&#xff0c;又过年了&#xff0c;于是又开摆 又想学了&#xff0c;家里面有有点小事&#xff0c;于是又开摆 摆完&#xff0c;没想到就返校啦 期末作业没完成&#xff08…...

singularity-ce-4.1.0 + go 完整安装步骤,及报错解决

singularity-ce-4.1.0 + go 1.20 完整安装步骤. 解决bug: checking: host Go compiler (at least version 1.13)... not found! mconfig: could not complete configuration服务器基础环境: 阿里云服务器: => lsb_release -a LSB Version: :core-4.1-amd64:core-4.1-n…...

笔记-电感充放电过程状态记录

描述&#xff1a;电感充放电过程状态记录 为加深对电感充放电的理解&#xff0c;特做一次记录。 目录 一、准备工作二、电感状态记录1、电感刚开始充电瞬间2、电感充电期间3、电感充电完毕4、电感开始放电瞬间5、电感放电完毕6、电感充放电完整记录 一、准备工作 1、在线平台…...

石头剪刀布游戏(C语言)

题目描述 石头剪刀布游戏有 3 种出拳形状&#xff1a;石头、剪刀、布。分别用字母 A , B , C 表示。 游戏规则: 出拳形状之间的胜负规则如下&#xff1a; A > B&#xff1b;B > C&#xff1b;C > A&#xff1b;">"左边一个字母&#xff0c;表示相对优…...

云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?

大家好&#xff0c;欢迎来到《云原生核心技术》系列的第七篇&#xff01; 在上一篇&#xff0c;我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在&#xff0c;我们就像一个拥有了一块崭新数字土地的农场主&#xff0c;是时…...

【JavaEE】-- HTTP

1. HTTP是什么&#xff1f; HTTP&#xff08;全称为"超文本传输协议"&#xff09;是一种应用非常广泛的应用层协议&#xff0c;HTTP是基于TCP协议的一种应用层协议。 应用层协议&#xff1a;是计算机网络协议栈中最高层的协议&#xff0c;它定义了运行在不同主机上…...

vscode(仍待补充)

写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh&#xff1f; debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...

1688商品列表API与其他数据源的对接思路

将1688商品列表API与其他数据源对接时&#xff0c;需结合业务场景设计数据流转链路&#xff0c;重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点&#xff1a; 一、核心对接场景与目标 商品数据同步 场景&#xff1a;将1688商品信息…...

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...

定时器任务——若依源码分析

分析util包下面的工具类schedule utils&#xff1a; ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类&#xff0c;封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz&#xff0c;先构建任务的 JobD…...

【python异步多线程】异步多线程爬虫代码示例

claude生成的python多线程、异步代码示例&#xff0c;模拟20个网页的爬取&#xff0c;每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程&#xff1a;允许程序同时执行多个任务&#xff0c;提高IO密集型任务&#xff08;如网络请求&#xff09;的效率…...

项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)

Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败&#xff0c;具体原因是客户端发送了密码认证请求&#xff0c;但Redis服务器未设置密码 1.为Redis设置密码&#xff08;匹配客户端配置&#xff09; 步骤&#xff1a; 1&#xff09;.修…...

【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)

本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...

Qemu arm操作系统开发环境

使用qemu虚拟arm硬件比较合适。 步骤如下&#xff1a; 安装qemu apt install qemu-system安装aarch64-none-elf-gcc 需要手动下载&#xff0c;下载地址&#xff1a;https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x…...