题目描述
实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。
如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。
必须原地修改,只允许使用额外常数空间。
以下是一些例子,输入位于左侧列,其相应输出位于右侧列。
1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1
8,4,7,6,5,3,1 → 8,5,1,3,4,6,7
思路
1. 从后向前遍历,判断当前数组是否为降序排列
2. 已为降序排列,说明不存在下一个更大的数,则 i 为 -1,直接反转0 - (len - 1)
3. 找到第一个num[i] < num[i + 1]的元素
4. 此时 i 必定 >= 0,然后继续从后向前,寻找第一个比num[i]大的元素,与num[i]进行交换
5. 反转 i 之后的元素
比如
| num | 8 | 4 | 7 | 6 | 5 | 3 | 1 |
|---|---|---|---|---|---|---|---|
| 下标 | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
| num[i] < num[i + 1] | i | ||||||
| num[i] < num[j] | j | ||||||
| swap(num, i, j) | 8 | 5 | 7 | 6 | 4 | 3 | 1 |
| reverse(num, i + 1, len - 1) | 8 | 5 | 1 | 3 | 4 | 6 | 7 |
代码:
class Solution {
public void nextPermutation(int[] nums) {
int i = nums.length - 2;
//寻找第一个num[i] < num[i + 1]的元素
while(i >= 0 && nums[i + 1] <= nums[i]){
--i;
}
//数组大小大于0,需要寻找下一个数
if(i >= 0){
int j = nums.length - 1;
//从后向前,寻找第一个比num[i]大的元素
while(j > i && nums[j] <= nums[i]){
--j;
}
//交换
swap(nums, i, j);
}
//反转i之后的元素
reverse(nums, i + 1);
}
//反转
public void reverse(int nums[], int left){
int i = left, j = nums.length - 1;
while(i < j){
swap(nums, i, j);
++i;
--j;
}
}
//交换
public void swap(int nums[], int i, int j){
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
}
来源:CSDN
作者:count的专栏
链接:https://blog.csdn.net/xiao_count/article/details/104069424