【LeetCode 热题 100】31. 下一个排列

Problem: 31. 下一个排列

文章目录

  • 整体思路
  • 完整代码
  • 时空复杂度
    • 时间复杂度:O(N)
    • 空间复杂度:O(1)

整体思路

这段代码旨在解决经典的 “下一个排列” (Next Permutation) 问题。问题要求重新排列一个整数数组,使其变为字典序上的下一个更大的排列。如果不存在更大的排列(即数组已经是降序排列),则将其重新排列为最小的排列(即升序排列)。这个操作必须在原地完成,只使用常数级的额外空间。

该算法是一种非常精巧的、基于观察的单次遍历解法。其核心思想是,要找到下一个更大的排列,我们需要从右向左找到第一个“破坏”降序趋势的数字,然后用一个比它稍大的数替换它,并对后面的部分进行排序以得到最小的增量。

算法的逻辑步骤可以分解为以下四步:

  1. 从右向左查找第一个“升序”对 (找到“小数”)

    • 算法从数组的倒数第二个元素 (i = n - 2) 开始向左扫描。
    • 它寻找第一个满足 nums[i] < nums[i + 1] 的索引 i
    • 为什么? 从右边看,只要 nums[i] >= nums[i+1] 持续成立,说明 [i, n-1] 这个后缀是一个降序(或非增序)序列。一个降序序列已经是它所能构成的最大排列。为了找到一个更大的排列,我们必须在更左边找到一个可以增大的“枢轴点”。这个 nums[i] 就是这个枢轴点,我们称之为“小数”。
  2. 从右向左查找第一个比“小数”大的数 (找到“大数”)

    • 在找到 i 之后,算法再从数组的最右端 (j = n - 1) 开始向左扫描。
    • 它寻找第一个满足 nums[j] > nums[i] 的索引 j
    • 为什么? 我们需要用一个比 nums[i] 大的数来替换它,以确保新的排列比旧的大。为了让这个增量尽可能小(以得到“下一个”排列),我们应该选择那个在后缀 [i+1, n-1] 中比 nums[i] 大的数里面最小的那个。由于后缀 [i+1, n-1] 是降序的,所以从右向左找到的第一个比 nums[i] 大的数 nums[j] 恰好就是这个“稍大”的数。
  3. 交换“小数”和“大数”

    • 找到 ij 后,交换 nums[i]nums[j] 的值。
    • 效果:此时,[0, i] 这部分已经确保了新的排列比原来的大。
  4. 反转“小数”位置之后的所有数

    • 在交换之后,后缀 [i+1, n-1] 仍然保持降序。
    • 为什么? 为了得到紧邻的下一个排列,我们需要让 [i+1, n-1] 这部分变为它所能构成的最小排列。一个降序序列的最小排列就是将其变为升序。
    • 因此,算法将 [i+1, n-1] 这个区间进行反转,使其变为升序。
  5. 特殊情况

    • 如果步骤1中的 while 循环结束后 i 变成了负数,这说明整个数组是完全降序的(如 [3, 2, 1])。此时不存在更大的排列,算法会跳过步骤2和3,直接执行步骤4,反转整个数组(从索引0开始),得到最小的排列(升序)。

完整代码

class Solution {/*** 找到并原地修改数组为下一个更大的字典序排列。* @param nums 整数数组*/public void nextPermutation(int[] nums) {int n = nums.length;// 步骤 1: 从右向左查找第一个“升序”对 (nums[i] < nums[i+1])// i 是这个“小数”的索引。int i = n - 2;while (i >= 0 && nums[i] >= nums[i + 1]) {i--;}// 如果 i >= 0, 说明找到了这样的“小数”,即数组不是完全降序的。if (i >= 0) {// 步骤 2: 从右向左查找第一个比 nums[i] 大的数// j 是这个“大数”的索引。int j = n - 1;while (nums[i] >= nums[j]) {j--;}// 步骤 3: 交换“小数”和“大数”swap(nums, i, j);}// 步骤 4: 反转“小数”位置之后的所有数// 如果 i < 0 (数组完全降序),这将反转整个数组,得到最小排列。// 否则,这将使交换后的后缀变为最小排列。reverse(nums, i + 1, n - 1);}/*** 辅助函数:交换数组中两个索引位置的元素。*/private void swap(int[] nums, int i, int j) {int t = nums[i];nums[i] = nums[j];nums[j] = t;}/*** 辅助函数:原地反转数组的指定区间 [left, right]。*/private void reverse(int[] nums, int left, int right) {while (left < right) {swap(nums, left++, right--);}}
}

时空复杂度

时间复杂度:O(N)

  1. 查找 i:第一个 while 循环最多扫描整个数组一次。在最坏情况下,时间复杂度为 O(N)
  2. 查找 j:第二个 while 循环最多扫描整个数组一次。在最坏情况下,时间复杂度为 O(N)
  3. 交换swap 操作是 O(1)
  4. 反转reverse 函数最多需要遍历 N/2 次交换,其操作的元素数量与 N 呈线性关系。在最坏情况下,时间复杂度为 O(N)

综合分析
整个算法由几次独立的、不嵌套的线性扫描组成。总的时间复杂度是 O(N) + O(N) + O(N) = O(N)

空间复杂度:O(1)

  1. 主要存储开销:该算法没有创建任何与输入规模 N 成比例的新的数据结构。
  2. 辅助变量:只使用了 n, i, j, t, left, right 等几个固定数量的整型变量。

综合分析
算法的所有操作都是在原数组上进行的(in-place),所需的额外辅助空间是常数级别的。因此,其空间复杂度为 O(1)

参考灵神

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

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

相关文章

【Linux 进程】进程程序替换

文章目录1.进程替换的六个库函数2.execl1.进程替换的六个库函数 使用 man 3 execl 进行查询&#xff0c;3表示 Linux 中的3号手册&#xff0c;即为库函数&#xff08;例如C标准库中的库函数&#xff0c;printf&#xff0c;malloc&#xff09; man 1: 用户命令&#xff08;在sh…

ReasonRank: Empowering Passage Ranking with Strong Reasoning Ability

主要内容总结 本文提出了一种具有强推理能力的列表式段落重排序模型ReasonRank,旨在解决现有重排序模型在推理密集型场景(如复杂问答、数学问题、代码查询等)中表现不佳的问题,核心原因是这类场景缺乏高质量的推理密集型训练数据。 为解决这一问题,研究团队: 设计了自动…

不卡顿、不掉线!稳定可靠的体育赛事直播系统源码解析

在体育和电竞行业&#xff0c;实时直播系统已经成为平台的标配。无论是 OTT、比分直播网站&#xff0c;还是综合类体育社区&#xff0c;用户对直播体验的要求越来越高&#xff1a;不卡顿、不掉线、实时性强。那么&#xff0c;从技术角度出发&#xff0c;一个稳定可靠的 体育赛事…

三菱FX5U PLC访问字变量的某一位

三菱FX5U PLC气缸控制功能块 三菱FX5U气缸控制功能块(完整ST源代码+示例程序)_三菱fx5u标签气缸报警程序功能块-CSDN博客文章浏览阅读560次,点赞5次,收藏2次。如果机器包含100个气缸,我们只需要修改数组的元素数量就可以了,效率非常的高。待续....博途PLC 面向对象系列之“…

Java大厂面试全真模拟:从Spring Boot到微服务架构实战

Java大厂面试全真模拟&#xff1a;从Spring Boot到微服务架构实战 面试场景&#xff1a;某互联网大厂Java后端岗位&#xff0c;候选人谢飞机&#xff08;水货程序员&#xff09; 第一轮&#xff1a;基础与框架认知 面试官&#xff1a;你好&#xff0c;谢飞机&#xff0c;先简单…

Unity游戏打包——Mac基本环境杂记

1、安装 Homebrew若未安装&#xff0c;在使用 brew 命令时将提示 zsh: command not found: brew安装命令&#xff1a;/bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)"2、更换终端默认 Shell 为 zsh查看已安装的shell&#…

服务组件体系结构(SCA)全景解析

服务组件体系结构&#xff08;SCA&#xff09;全景解析SCA&#xff08;Service Component Architecture&#xff09;是 SOA 生态中专门用来“把服务拼起来并跑起来”的规范。它通过语言中立、协议可插拔、装配声明式三大能力&#xff0c;把“接口—实现—协议”彻底解耦&#x…

问:单证硕士含金量是否不足?

很多人认为花几万块钱读一个同等学历申硕&#xff0c;含金量并没有那么高&#xff0c;但事实却并非如此。今天我们从证书和学习的两个方面来聊一下同等学历申硕的含金量到底是如何的。一、单证含金量看以下几点&#xff1a;&#xff08;1&#xff09;国家认证与学信网可查 …

0.04% vs 0.1%:精度差一点,逆变器性能差距有多大?

一台光伏逆变器损失的功率可能仅仅源于0.3%的MPPT效率差距。这个足以影响产品竞争力的数字&#xff0c;可能并非算法优劣&#xff0c;而在于测试源头的精度选择&#xff1a;是0.04%还是0.1%&#xff1f;本文通过四大测试场景的量化对比&#xff0c;揭示不同的测试精度如何影响产…

Docker Hub 镜像一键同步至阿里云 ACR

&#x1f433; Docker Hub 镜像一键同步至阿里云 ACR 本脚本用于 从 Docker Hub 拉取镜像并推送到阿里云容器镜像服务&#xff08;ACR&#xff09;。 它通过 Python 的 docker SDK 封装了完整流程&#xff1a;拉取 → 重命名 → 登录 → 推送&#xff0c;并在控制台实时输出进度…

软考-系统架构设计师 计算机系统基础知识详细讲解

个人博客&#xff1a;blogs.wurp.top 一、计算机系统组成与多级层次结构 1. 冯诺依曼体系结构 (核心考点) 这是所有现代计算机的理论基础。核心思想是 “存储程序” 。 五大部件&#xff1a;运算器、控制器、存储器、输入设备、输出设备。工作流程&#xff1a;指令驱动。CP…

DLL文件丢失怎么办?这个修复工具一键搞定!

软件介绍&#xff08;文末获取&#xff09;是不是经常遇到这种情况&#xff1a;安装软件时提示缺少DLL文件&#xff1f;打开游戏时出现DLL错误&#xff1f;或者运行程序时突然崩溃&#xff1f;今天给大家推荐一款超好用的DLL修复工具——4DDiG DLL Fixer&#xff0c;一键解决所…

并发容器小结及ConcurrentSkipListMap介绍——并发系列(十一)

目录 概述 ConcurrentHashMap CopyOnWriteArrayList ConcurrentLinkedQueue BlockingQueue ConcurrentSkipListMap 设计目的 功能特性 与其他相关类对比 适用场景 概述 JDK提供的这些容器大部分在 java.util.concurrent 包中。我们这里挑选出了一些比较有代表性的并发…

蓝思科技半年净利超11亿,蓝思成绩单怎么分析?

8月26日&#xff0c;蓝思科技发布2025年半年度业绩报告&#xff0c;其中&#xff0c;净利润11.43亿元&#xff0c;同比增长32.68%。这份成绩单我们该怎么分析&#xff1a;首先&#xff0c;蓝思科技营收与利润双增长&#xff0c;成长能力持续凸显。报告期内&#xff0c;公司营业…

【GM3568JHF】FPGA+ARM异构开发板 应用编辑及源码下载

早期因为处理器芯片性能不够&#xff0c;存储空间不多以及编译性能不够等因素&#xff0c; 早期的开发板普遍采用交叉编译的方式&#xff0c; 而交叉编译的方式会有几种缺点&#xff1a; 不能离线编译&#xff0c; 操作麻烦&#xff0c; 环境配置复杂等 GM-3568JHF的处理器性能…

华为仓颉语言的函数初步

华为仓颉语言的函数初步函数是一段完成特定任务的独立代码片段&#xff0c;可以通过函数名字来标识&#xff0c;这个名字可以被用来调用函数。要特别注意&#xff0c;与C/C、Python等语言不同&#xff0c;仓颉禁止参数重新赋值——函数参数均为不可变&#xff08;immutable&…

服务初始化

目录 1.配置yum源 2. 更新系统与安装必备工具 3. 网络连接验证 4. 配置主机名 5. 同步时间 6. 配置防火墙 (两种方式) 6.1 iptables 6.2firewalld 1.配置yum源 1. 备份原有的源文件&#xff0c;以防万一 mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.…

ICBC_TDR_UShield2_Install.exe [ICBC UKEY]

流程&#xff1a;1&#xff09;插入U盾&#xff0c;记住检测到U盾类型&#xff0c;需要根据这个下载驱动

在线提取维基百科Wikipedia文章页面及离线批处理Wikipedia XML Dump文件

1. 在线提取维基百科Wikipedia文章 本项目提供一个增强型 Wikipedia 概念条目抓取与摘要清洗脚本&#xff1a;支持多级回退策略 (wikipedia 库 →wikipediaapi → 直接网页 / REST 搜索)、智能标题匹配(精确/模糊判定)、摘要质量校验、内容结构化抽取、断点续跑(结果缓存)、统…

安全合规:AC(上网行为安全)--下

五、SSL移动接入方案概述1、SSL VPN概述SSL VPN是一种远程安全接入技术&#xff0c;因为采用SSL协议而得名。因为Web浏览器都内嵌支持SSL协议&#xff0c;使得SSL VPN可以做到“无客户端”部署。SSL VPN一般采用插件系统来支持各种TCP和UDP的非Web应用&#xff0c;使得SSL VPN真…