实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。必须原地修改,只允许使用额外常数空间。
示例 1:
输入:nums = [1,2,3]
输出:[1,3,2]
解题思路:
-
先找出最大的索引 i 满足 nums[i] < nums[i+1],如果不存在,就翻转整个数组;
-
再找出另一个最大索引 j 满足 nums[j] > nums[i];
-
交换 nums[i] 和 nums[j];
-
最后翻转 nums[j+1:]
代码:
class Solution {
public void nextPermutation(int[] nums) {
int n = nums.length;
//1. 先找出最大的索引 i 满足 nums[i] < nums[i+1],确定i
int i = -1;
// 从后向前遍历
for(int index = n - 2; index >= 0; index--) {
if(nums[index] < nums[index + 1]) {
i = index;
break;
}
}
// 如果不存在,表明不存在下一个更大的排列,就翻转整个数组
if(i == -1) {
reverse(nums, 0, n - 1);
return;
}
//2. 再找出另一个最大索引 j 满足 nums[j] > nums[i],确定j
int j = -1;
// 从后向前遍历
for(int index = n - 1; index >= 0; index--) {
if(nums[index] > nums[i]) {
j = index;
break;
}
}
// 交换 nums[i] 和 nums[j];
swap(nums, i, j);
// 最后翻转 nums[j+1:]
reverse(nums, i + 1, n - 1);
return;
}
//反转
public void reverse(int[] nums, int i, int j) {
int left = i;
int end = j;
while(left < end) {
swap(nums, left++, end--);
}
}
//交换
public void swap(int[] nums, int i, int j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}
时间复杂度:O(n)
空间复杂度:O(1)
这篇博客介绍了如何使用原地修改的方法找到一个数字序列的下一个字典序排列。通过找到最大索引i使得nums[i]<nums[i+1],然后找到大于nums[i]的最小子数组,交换这两个元素并反转子数组来达到目的。如果不存在这样的i,则直接反转整个数组得到最小排列。算法的时间复杂度为O(n),空间复杂度为O(1)。
930

被折叠的 条评论
为什么被折叠?



