31. 下一个排列
题目描述:
整数数组的一个 排列 就是将其所有成员以序列或线性顺序排列。
- 例如,arr = [1,2,3] ,以下这些都可以视作 arr 的排列:[1,2,3]、[1,3,2]、[3,1,2]、[2,3,1] 。
整数数组的 下一个排列 是指其整数的下一个字典序更大的排列。更正式地,如果数组的所有排列根据其字典顺序从小到大排列在一个容器中,那么数组的 下一个排列 就是在这个有序容器中排在它后面的那个排列。如果不存在下一个更大的排列,那么这个数组必须重排为字典序最小的排列(即,其元素按升序排列)。
- 例如,arr = [1,2,3] 的下一个排列是 [1,3,2] 。
- 类似地,arr = [2,3,1] 的下一个排列是 [3,1,2] 。
- 而 arr = [3,2,1] 的下一个排列是 [1,2,3] ,因为 [3,2,1] 不存在一个字典序更大的排列。
给你一个整数数组 nums ,找出 nums 的下一个排列。必须 原地 修改,只允许使用额外常数空间。
解题思路:
示例:
arr = [1,2,3]的全部顺序排序为: [1,2,3] [1,3,2] [2,1,3] [2,3,1] [3,1,2] [3,2,1]
我们应该从后往前遍历相邻两个数字,只要遇到正常升序的两数字,交换它们俩的位置必然能得到一个比原先排列大的排列(如:[1,3,2] -> [3,1,2])。但这并不能保证交换之后得到的是下一个排列,因为后面有比‘3’更小的数字‘2’,将它与‘1’交换得到的排列[2,3,1]比[3,1,2]更接近[1,3,2];但这也不是[1,3,2]的下一排列,因为[2,3,1]数字‘2’后面的序列如果能按升序顺序排列能得到更小的排序[2,1,3],这才是真正的下一排列。因此可以总结出解题步骤如下:
- 从后往前遍历,找到升序顺序的相邻两数字 nums[i] 与 nums[i+1] ;
- 重新从后往前遍历,找到比 nums[i] 大的数字 nums[j] ,可以保证数字 nums[j] 是子排列 [nums[i+1],nums[i+2],...,nums[n-1]] 中的最小数字;
- 交换 i 与 j 的位置;
- 由于交换之后的子排列 [nums[i+1],nums[i+2],...,nums[n-1]] 必然为非升序,因此只需要将子排列进行反转便可以得到升序的子排序,最后得到的排列就是下一排列。
算法正确性证明:
以 [...,3,7,5,3,2,1] 这个排列说明一下,在第一步中,我们是以“找升序顺序的两数字”为目的从后往前遍历数组的。因此,在找到数字‘3’之前,遍历过的序列[7,5,3,2,1]必然“满足前一个数字大于或等于后一个数字”(也即非升序)。找到数字‘3’后,我们又在遍历过的序列[7,5,3,2,1]中找比‘3’大的数字‘5’,交换位置后的序列[7,3,3,2,1]必然也满足非升序顺序。因为 nums[i] >=nums[j+1]>=nums[j+2]>=... ,而nums[j-1]>=nums[j],因此交换nums[i]与nums[j]之后,由于nums[j]>nums[i],所以交换过后的子序列:...>nums[j-1]>nums[i]>=nums[j-1]>=...,满足非升序顺序。
代码实现:
/** * @param {number[]} nums * @return {void} Do not return anything, modify nums in-place instead. */ var nextPermutation = function(nums) { let i = nums.length-2; //对于长度为1的nums,直接跳过循环 for(;i>=0;i--){ if(nums[i]<nums[i+1]){ for(let j=nums.length-1;j>=i+1;j--){ if(nums[j]>nums[i]){ swap(nums,i,j); break; } } reverse(nums,i+1); break; } } //如果整个nums为降序序列,那么它的下一排列就是升序序列,直接反转即可 if(i<0){ reverse(nums,0); } }; function swap(nums,i,j){ let temp = nums[i]; nums[i] = nums[j]; nums[j] = temp; } function reverse(nums,start){ let i = start; let j = nums.length-1; while(i<j){ swap(nums,i,j); i++; j--; } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)