搜索回溯算法—全排列 II(leetcode 47)

2023-11-08

题目描述

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

算法分析

方法一:搜索回溯

思路和算法

此题是「46. 全排列」的进阶,序列中包含了重复的数字,要求我们返回不重复的全排列,那么我们依然可以选择使用搜索回溯的方法来做。

我们将这个问题看作有 n个排列成一行的空格,我们需要从左往右依次填入题目给定的 n个数,每个数只能使用一次。那么很直接的可以想到一种穷举的算法,即从左往右每一个位置都依此尝试填入一个数,看能不能填完这 n个空格,在程序中我们可以用「回溯法」来模拟这个过程。

我们定义递归函数 backtrack(idx, perm) 表示当前排列为 perm,下一个待填入的位置是第 idx 个位置(下标从 0开始)。那么整个递归函数分为两个情况:

    如果 idx==n,说明我们已经填完了 n个位置,找到了一个可行的解,我们将 perm放入答案数组中,递归结束。

   如果 idx

但题目解到这里并没有满足「全排列不重复」 的要求,在上述的递归函数中我们会生成大量重复的排列,因为对于第 idx的位置,如果存在重复的数字 iii,我们每次会将重复的数字都重新填上去并继续尝试导致最后答案的重复,因此我们需要处理这个情况。

要解决重复问题,我们只要设定一个规则,保证在填第 idx个数的时候重复数字只会被填入一次即可。而在本题解中,我们选择对原数组排序,保证相同的数字都相邻,然后每次填入的数一定是这个数所在重复数集合中「从左往右第一个未被填过的数字」,即如下的判断条件:

if (i > 0 && nums[i] == nums[i - 1] && !vis[i - 1]) {
    continue;
}

这个判断条件保证了对于重复数的集合,一定是从左往右逐个填入的。

假设我们有 3个重复数排完序后相邻,那么我们一定保证每次都是拿从左往右第一个未被填过的数字,即整个数组的状态其实是保证了 [未填入,未填入,未填入] 到 [填入,未填入,未填入],再到 [填入,填入,未填入],最后到 [填入,填入,填入] 的过程的,因此可以达到去重的目标。

代码

class Solution {
private:
    vector<bool> status;
public:
    void backtrack(vector<int> &nums, vector<vector<int>> &res, vector<int> &track, int idx) {
        if(idx == nums.size()) {
            res.emplace_back(track);
            return;
        }
        for(int i = 0; i < nums.size(); ++i) {
            if(status[i] || (i > 0 && nums[i] == nums[i-1] && !status[i-1])) {
                continue;
            }
            track.push_back(nums[i]);
            status[i] = true;
            backtrack(nums, res, track, idx+1);
            status[i] = false;
            track.pop_back();
        }
    }
    vector<vector<int>> permuteUnique(vector<int>& nums) {
        vector<vector<int>> ans;
        vector<int> track;
        status.resize(nums.size(), false);
        sort(nums.begin(), nums.end());
        backtrack(nums, ans, track, 0);
        return ans;
    }
};

时间复杂度分析

时间复杂度:O(n×n!),其中 n为序列的长度。

空间复杂度:O(n)。我们需要 O(n)的标记数组,同时在递归的时候栈深度会达到 O(n),因此总空间复杂度为 O(n+n)=O(2n)=O(n)O(n + n)=O(2n)=O(n)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

搜索回溯算法—全排列 II(leetcode 47) 的相关文章

  • AXI4-Stream协议的信号以及Xilinx提供的从AXI到AXI-Stream转换的IP核区别

    AXI4 Stream协议是一种用来连接需要交换数据的两个部件的标准接口 它可以用于连接一个产生数据的主机和一个接受数据的从机 当然它也可以用于连接多个主机和从机 该协议支持多种数据流使用相同共享总线集合 允许构建类似于路由 宽窄总线 窄宽
  • LaTex论文格式模板

    LaTex论文格式模板 效果如图 代码 使用的是工具是 VSCode texlive TEX program xelatex documentclass 12pt a4paper article 文档格式 usepackage ctex h

随机推荐

  • RSync详解

    简介 rsync remote synchronize 是一款实现远程同步功能的软件 它在同步文件的同时 可以保持原来文件的权限 时间 软硬链接等附加信息 rsync是用 rsync 算法 提供了一 个客户机和远程文件服务器的文件同步的快速
  • 大数据期末课设~基于spark的气象数据处理与分析

    目录 一 项目背景 3 二 实验环境 3 三 实验数据来源 4 四 数据获取 5 五 数据分析 17 六 数据可视化
  • 【论文精读AAAI_2022】MobileFaceSwap: A Lightweight Framework for Video Face Swapping

    论文精读AAAI 2022 MobileFaceSwap A Lightweight Framework for Video Face Swapping 一 前言 Abstract Introduction Related Work Fac
  • Using a debugger

    Java IDE 中最有用的特性之一就是它们的 debuggers 它可以接入到运行着你的应用的JVM中 允许你在任何位置暂停代码的执行 以便检查应用的状态 要调试 Play 应用 需要将其以 debug 模式启动 然后把你的 debugg
  • FastDFS集群部署和同步机制

    如何选择tracker 当集群中有多个tracker server时 由于tracker之间是对等的关系 客户端在upload文件时可以任意选择一个tracker 如何选择storage 当选定group后 tracker会在group内选
  • 面部五官迁移算法(Python)

    面部器官互换指的是 将一个人的面部器官换到另一个人的脸上 比如将A的眼睛换到B的眼睛上 算法的实现技术要点为 关键点检测 人脸对齐 mask制作 色差矫正 mask融合 关键点检测 是使用的dlib81个关键点模型 人脸对齐是基于放射变换做
  • 爬虫项目七:Python对唯品会商品数据、评论数据的爬取

    文章目录 前言 一 商品数据 1 分析页面 2 分析url 3 解析数据 二 评论数据 1 抓包 2 分析url 3 获取数据 三 总结 前言 用Python爬取唯品会商品数据 评论数据 提示 以下是本篇文章正文内容 下面案例可供参考 一
  • binascii模块常用四个方法介绍

    python代码中处理加解密时 可能你会用到base64模块来进行编码 而base64模块实际上又去调用binascii模块 那么binascii模块中最常用的四个方法 函数 是哪些呢 具体什么用途呢 介绍四个方法之前 先说明一点 bina
  • 开源游戏引擎介绍

    2D Allegro cc Main http www allegro cc 老牌子了 和SDL同时是很经典两个EG开发组件 最近貌似在和PY进行联合 ClanLib ClanLib Game SDK http www clanlib or
  • erp服务器配置

    erp服务器配置 如果是做ERP服务器的话 推荐用双路四核的 这样比较有扩展性 如果以后客户端数量增加了或者数据库文件越跑越大 对性能要求增加 双路服务器的扩展性优势就出来了 你可以看看国产品牌正睿的这款最新SNB E架构的双路四核服务器
  • 【华为OD机试python】拔河比赛【2023 B卷

    华为OD机试 真题 点这里 华为OD机试 真题考点分类 点这里 题目描述 公司最近准备进行拔河比赛 需要在全部员工中进行挑选 选拔的规则如下 按照身高优先 体重次优先的方式准备比赛阵容 规定参赛的队伍派出10名选手 请实现一个选拔队员的小程
  • 汕头刀片服务器维修,刀片服务器怎么拆外壳

    刀片服务器怎么拆外壳你知道吗 下面学习啦小编为大家整理了刀片服务器内部结构详解的内容 欢迎参阅 刀片服务器拆外壳的方法 首先是龙芯刀片CB50 A的机箱 乍看起来很眼熟 原来是曙光TC2600刀片服务器机箱 熟悉的朋友知道 著名的超级计算机
  • Handler 细节分析

    Handler 常见问题分析 1 Handler 机制中涉及到那些类 各自的功能是什么 2 有哪些发送消息的方法 3 MessageQueue 中的 Message 是有序的吗 排序的依据是什么 4 Message when 是指的是什么
  • 使用KVM虚拟机安装Linux

    KVM虚拟系统管理器 基于内核的虚拟机 Kernel based Virtual Machine 简称KVM 是一种内建于 Linux 中的开源虚拟化技术 具体而言 KVM 可帮助你将 Linux 转变为虚拟机监控程序 使主机计算机能够运行
  • vue做色带

    项目中需要用到色带去设置定量的栅格图层在geoserver显示的样式 记录一下 将下拉框选项设置为图片 渐变颜色 每个选项对应两个颜色 将两个颜色传递到后端即可 样式如下图所示 下拉框结构
  • 【Linux

    目录 一 概述 二 test 命令 2 1 test 命令 2 2 方括号测试条件 2 3 test 命令和测试条件可以判断的 3 类条件 2 3 1 数值比较 2 3 2 字符串比较 三 复合条件测试 四 if then 的高级特性 五
  • 谷歌浏览器单独下载插件文件crx到本地的方法步骤

    描述 谷歌浏览器单独下载插件文件crx到本地的方法步骤 步骤 打开网站 搜索插件名称 https www crx4chrome com 进入详情页 点击Download crx file from Crx4Chrome crx文件已经下载到
  • stm32 mbed入门教程(一)mbed IDE与第一个程序

    mbed os是一个简化编写的架构 与其类似的还有Arduino生态环境 是一种大幅度的减少编程要求 快速达到用户需求的一套开发架构 而mbed ide 及其一整套在线编程 拷贝式下载方法 则是这一套架构的开发平台及其执行方法 这一篇将介绍
  • 如何通过cmd找文件

    在学习的过程中 老师要找丢在各个角落的文件 这次主要找得是C盘里面的my ini文件 如果不知道在哪个盘 就每个盘改一下C变成D dir C my ini s b cmd里面的运行结果 找不到的结果
  • 搜索回溯算法—全排列 II(leetcode 47)

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