Leetcode 剑指 Offer II 083.全排列

news2024/10/7 18:30:52

题目难度: 中等

原题链接

今天继续更新 Leetcode 的剑指 Offer(专项突击版)系列, 大家在公众号 算法精选 里回复 剑指offer2 就能看到该系列当前连载的所有文章了, 记得关注哦~

题目描述

给定一个不含重复数字的整数数组 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 中的所有整数 互不相同

题目思考

  1. 如果限制只能用递归或者迭代, 如何解决?

解决方案

方案 1

思路
  • 由于给定数组的各个数字都不相同, 所以我们可以每次从中挑选一个还未用过的数字, 将其加入当前排列中, 这样由于每次挑选的顺序不同, 最终形成的排列也各不相同
  • 这就是典型递归的思想, 具体做法如下:
    1. 维护两个数组, 分别代表当前剩余未使用的数字, 以及当前的排列
    2. 针对当前未使用的数字, 逐一遍历它们, 并将其追加到当前排列中, 这样就保证了每个排列数字的顺序各不相同
    3. 然后继续传入新的未使用数字和排列, 继续递归调用
    4. 最后当未使用数字为空时结束递归, 此时就形成了一个有效的排列
  • 下面的代码中有详细的注释, 方便大家理解
复杂度
  • 时间复杂度 O(N!): N 个数字各不相同, 排列就有 N!
  • 空间复杂度 O(N): 递归栈, 剩余数字以及当前排列的空间占用最多都是 N
代码
Python 3
class Solution:
    def permute(self, nums: List[int]) -> List[List[int]]:
        # 方法1: 简单递归
        res = []

        def dfs(remain, perm):
            # remain是剩余数字对应的数组
            # perm是当前排列
            if not remain:
                # 没有剩余数字了, 将当前排列加入最终结果中
                # 因为nums没有重复数字, 所以保证了最终每个排列都各不相同
                res.append(perm)
                return
            for i in range(len(remain)):
                # 选择remain中的各个数字追加到当前排列中, 然后继续递归
                dfs(remain[:i] + remain[i + 1 :], perm + [remain[i]])

        # 初始时剩余数字数组为整个nums, 当前排列为空
        dfs(nums, [])
        return res

方案 2

思路
  • 接下来我们尝试用迭代的思路来解决
  • 我们可以定义一个方法, 来求按顺序的下一个排列, 例如[1,2,3]->[1,3,2]->[2,1,3]->[2,3,1]->[3,1,2]->[3,2,1], 这样就能保证得到每个不重复的排列
  • 先将给定数组按升序排序, 然后当遍历到的排列变成降序排序的时候, 就说明所有排列都被找到了
  • 所以算法的核心就是如何通过一个排列找它按顺序的下一个排列
  • 下一个排列一定是所有排列中大于当前排列且最接近它的, 所以我们可以利用贪心算法, 具体步骤如下:
    1. 从后向前找第一个小于后一个数字的下标 i (因为如果大于等于后一个数字的话, 就没法与后面的数字交换来使得整体排列更大了)
    2. 找刚才遍历的部分的大于且最接近下标 i 对应数字的下标 j
    3. 将它们两个互换
    4. 然后 i 往后的部分都按升序排列, 也即将这部分逆序 (因为现在这部分是降序排序的)
  • 这样就保证了新的排列一定是大于当前排列且最接近它的, 不可能有更小的了
  • 下面的代码中有详细的注释, 方便大家理解
复杂度
  • 时间复杂度 O(N*N!): N 个数字各不相同, 排列就有 N! 种, 从当前排列转入下一个排列需要 O(N) 时间
  • 空间复杂度 O(1): 只使用了几个常数空间的变量 (不考虑输出结果集)
代码
Python 3
class Solution:
    def permute(self, nums: List[int]) -> List[List[int]]:
        # 方法2: 迭代getNext
        res = []
        n = len(nums)

        def getNext(nums):
            for i in range(n - 1)[::-1]:
                # 从后向前查找
                if nums[i] < nums[i + 1]:
                    # 找到目标数字了, 接下来找后面部分中大于nums[i]且最接近它的数字
                    j = i + 1
                    while j < n and nums[j] > nums[i]:
                        j += 1
                    # 此时nums[j]<=nums[i], 将它减1后的nums[j]就是后面部分中大于nums[i]且最接近它的数字, 它需要和nums[i]互换
                    j -= 1
                    # 单独拿出新的右边部分(已经将下标i和j互换了), 肯定严格按照降序排列
                    right = nums[i + 1 : j] + [nums[i]] + nums[j + 1 :]
                    # 将三部分拼接起来, 注意右边部分要逆序, 这样就变成升序排列
                    return nums[:i] + [nums[j]] + right[::-1]
            # 没找到下一个排列, 说明当前排列就是顺序最大的了, 直接返回None
            return None

        # 先拿到顺序最小的排列
        nums.sort()
        while nums:
            res.append(nums)
            nums = getNext(nums)
        return res

大家可以在下面这些地方找到我~😊

我的 GitHub

我的 Leetcode

我的 CSDN

我的知乎专栏

我的头条号

我的牛客网博客

我的公众号: 算法精选, 欢迎大家扫码关注~😊

算法精选 - 微信扫一扫关注我

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

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

相关文章

轻量级日志系统——Loki

目录 一、loki简介 二、Loki 快速上手 第一步安装 Loki 第二步安装 Promtail 第三步安装granafa 三、LogQL 语法 四、Loki收集nginx日志 1、修改nginx配置 2、nginx服务器上安装promtail 3、添加doshbarod 一、loki简介 Loki是 Grafana Labs 团队最新的开源项目&am…

【图解IO与Netty系列】Netty源码解析——事件循环

Netty源码解析——事件循环 Netty事件循环源码解析select()processSelectedKeys()NioMessageUnsafe#read()NioByteUnsafe#read() runAllTasks() Netty事件循环 当Netty服务端启动起来以后&#xff0c;就可以接受客户端发送的请求&#xff0c;接收到客户端发来的请求后就会有事…

大数据学习-大数据介绍

意义 从海量的数据中分析出海量数据背后的价值 需要分析海量的数据&#xff0c;就需要存储、计算和分析 那就需要分布式多台计算机合适的工具来处理数据 工具 特点 大数据的核心工作&#xff1a;从海量的、高增长的、多类别的、信息密度低的数据中挖掘出高质量的结果 数据存储…

RedHat9 | Web服务配置与管理(Apache)

一、实验环境 1、Apache服务介绍 Apache服务&#xff0c;也称为Apache HTTP Server&#xff0c;是一个功能强大且广泛使用的Web服务器软件。 起源和背景 Apache起源于NCSA httpd服务器&#xff0c;经过多次修改和发展&#xff0c;逐渐成为世界上最流行的Web服务器软件之一。…

C++ STL ③

sort排序 #include <iostream> #include <algorithm> using namespace std;int main() {int a[5],i;cout<<"请输入数组元素:"<<endl;for(i0;i<5;i){cin>>a[i];}sort(a,a5,greater<int>());for(i0;i<5;i){cout<<a[i…

系统架构师考点--数据库系统

大家好。今天我来总结一下数据库系统的相关考点。本考点一般情况下上午场考试占3-5分&#xff0c;下午场案例分析题也会出现。 一、数据库系统 数据&#xff1a;数据库中存储的基本对象&#xff0c;是描述事物的符号记录。数据的种类:文本、图形、图像、音频、视频、学生的档…

基于Redis和openresty实现高并发缓存架构

目录 概述缓存架构设计实践代码路由业务封装redis 效果 概述 本文是对项目中 QPS 高并发相关问题的一种解决方案&#xff0c;利用 Nginx 与 Redis 的高并发、超低延迟响应&#xff0c;结合 Canal 进行实现。 openrestry官网 当程序需要提供较高的并发访问时&#xff0c;往往需…

状态压缩DP——AcWing 291. 蒙德里安的梦想

状态压缩DP 定义 状态压缩DP是一种利用二进制数来表示状态的动态规划算法。它通过将状态压缩成一个整数&#xff0c;从而减少状态数量&#xff0c;提高算法效率。 运用情况 状态压缩DP通常用于解决具有状态转移和最优解性质的问题&#xff0c;例如组合优化、图论、游戏等问…

UDS服务——TransferData (0x36)

诊断协议那些事儿 诊断协议那些事儿专栏系列文章,本文介绍TransferData (0x36)—— 数据传输,用于下载/上传数据时用的,数据的传输方向由不同的服务控制:0x34服务表示下载,0x35服务表示上传。通过阅读本文,希望能对你有所帮助。 文章目录 诊断协议那些事儿传输数据服务…

Redis-事务-watch-unwatch

文章目录 1、监视key2、提交事务 1、监视key 打开两个窗口&#xff0c;第一个窗口先监视key&#xff0c;然后开始事务&#xff0c;然后再打开第二个窗口&#xff0c;修改balance为0 2、提交事务 此时事务被打断

银河麒麟V10 SP1.1操作系统 离线安装 nginx1.21.5、redis 服务

银河麒麟官网地址&#xff1a;国产操作系统、麒麟操作系统——麒麟软件官方网站 一、查看系统版本 命令&#xff1a;nkvers 我的是 release V10 (SP1)&#xff0c;根据这个版本去官网找对应的rpm包 银河麒麟操作系统的rpm包必须从官方找&#xff0c; 要是随便找个Centos的rp…

1.SG90

目录 一.实物图 二.原理图 三.简介 四.工作原理 一.实物图 二.原理图 三.简介 舵机&#xff08;英文叫Servo&#xff09;&#xff0c;是伺服电机的一种&#xff0c;伺服电机就是带有反馈环节的电机&#xff0c;这种电机可以进行精确的位置控制或者输出较高的扭矩。舵机…

基于深度学习的图像识别技术与应用是如何?

基于深度学习的图像识别技术与应用在当今社会中扮演着越来越重要的角色。以下是对该技术与应用的详细解析&#xff1a; 一、技术原理 深度学习是一种模拟人脑处理和解析数据的方式的技术和方法论。在图像识别领域&#xff0c;深度学习主要通过深度神经网络&#xff08;如卷积…

我理解的文本表示模型

词袋模型与N-grams模型 1 词袋模型 (Bag of Words)1.1 one-hot 取值 (Binary)1.2 Term Frequency 取值 (TF)普通频数 r a w t f raw_{tf} rawtf​频率范数归一化对数频数 1.3 Inverse document frequency (IDF)1.4 TF-IDF scores 取值 N-Gram 最简单的文本建模场景&#xff1a…

定义多个类对象,分别输入和输出各对象中的时间(时:分:秒)

在前面的文章中&#xff0c;类中只有公用数据而无成员函数&#xff0c;而且只有1个对象。可以直接在主函数中进行输入和输出。若有多个对象&#xff0c;需要分别引用多个对象中的数据成员&#xff0c;可以写出如下程序&#xff1a; &#xff08;1&#xff09;编写程序&#xff…

stata17中java installation not found或java not recognozed的问题

此问题在于stata不知道去哪里找java,因此需要手动的告诉他 方法1&#xff1a; 1.你得保证已经安装并配置好java环境 2.在stata中输入以下内容并重启stata即可 set java_home "D:\Develope\JDk17" 其中java_home后面的""里面的内容是你的jdk安装路径 我的…

【Java算法】滑动窗口 上

&#x1f525;个人主页&#xff1a; 中草药 &#x1f525;专栏&#xff1a;【算法工作坊】算法实战揭秘 &#x1f456;一. 长度最小的子数组 题目链接&#xff1a;209.长度最小的子数组 算法原理 滑动窗口 滑动窗口算法常用于处理数组/字符串等序列问题&#xff0c;通过定义一…

IKVM.net调用Jar包实现SM4解密

近期&#xff0c;我深入学习了如何使用IKVM.net来调用Jar包&#xff0c;这次的学习经历让我对Java与.NET之间的互操作性有了更深刻的理解。IKVM.net作为一款强大的工具&#xff0c;为我们打通了Java与.NET之间的桥梁&#xff0c;使得在.NET环境中调用Java库变得简单而高效。 在…

生产环境安装odoo

odoo可以在多平台运行&#xff0c;但是在生产环境下官方不建议在Windows平台部署。在Windows下可能不能很好的支持一服务多worker的形式&#xff0c;更推荐在Linux下部署。 常见的Linux如Ubuntu、Debian等Debian系或Redhat系都能执行官网的包安装。 地址&#xff1a;Download |…

使用Jetpack Compose为Android App创建自定义页面指示器

使用Jetpack Compose为Android App创建自定义页面指示器 在现代移动应用中&#xff0c;页面指示器在提供视觉导航提示方面发挥着重要作用&#xff0c;帮助用户理解其在应用内容中的当前位置。页面指示器特别适用于顺序展示内容的场景&#xff0c;如图片轮播、图像库、幻灯片放…