31. 下一个排列
难度中等1450
实现获取 下一个排列 的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列(即,组合出下一个更大的整数)。
如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。
必须** 原地 **修改,只允许使用额外常数空间。
示例 1:
输入:nums = [1,2,3]
输出:[1,3,2]
示例 2:
输入:nums = [3,2,1]
输出:[1,2,3]
示例 3:
输入:nums = [1,1,5]
输出:[1,5,1]
示例 4:
输入:nums = [1]
输出:[1]
提示:
1 <= nums.length <= 100
0 <= nums[i] <= 100
题解
找到妙处 用双指针解
前提是要懂整个过程 , 按照代码画图简单模拟一下
class Solution {
public void nextPermutation(int[] nums) {
int n = nums.length;
if(n <= 1) return; //一个数或者没有数下一个排列个锤子 直接返回
//然后从后往前找 找到第一处升序处 123 -> 23 就是第一个升序处 321 -> 找到头都没有 直接反转就是下一个排列
int i = n-2;
while(i>=0 && nums[i] >= nums[i+1]) i--; //-1就是极限 也就是直接反转的条件
if(i == -1) reserve(nums,0,n-1); //全部反转
else{
//没有到-1 也就是123的情况 现在的i是在2的位置
//然后就是继续从后往前找找到第一个严格大于2(i所指的)的第一个数
int j = n-1; //从最后一个数开始找
while(nums[j]<=nums[i]) j--;
swap(nums,i,j); //交换nums[i] 和 nums[j]的值
reserve(nums,i+1,n-1); //反转i(不包括i)后面的所有值
}
}
//交换函数
public void swap(int[] nums,int i, int j){
int temp = nums[i]; nums[i] = nums[j]; nums[j] = temp;
}
//反转函数
public void reserve(int[] nums, int start, int end){
while(start<=end) swap(nums,start++,end--);
}
}