题目:
实现获取 下一个排列 的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。
如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。
必须 原地 修改,只允许使用额外常数空间。
示例 :
输入:[4,2,0,2,3,2,0]
输出:[4,2,0,3,0,2,2]
解题思路:
找下一个排列更大的数,我们尽可能的将低位的数字变大,其实就是将k位到最低位的所有数作为候选,判断是否有更大的数可以填入k位中,换句话说,我们要找的第k位其实就是从低位到高位第一个下降的数。
进行一下步骤:
1. 从后往前找,找到第一个下降的位置,记为 k
。注意k
以后的位置是降序的。
2. 从 k 往后找,找到最小的比 k 要大的数。
3. 将两者交换。注意此时 k
以后的位置仍然是降序的。
4. 直接将 k 以后的部分翻转(变为升序)。
注意:如果在步骤 1 中找到头部还没找到,说明该序列已经是字典序最大的排列。按照题意,我们要将数组重新排列成最小的排列。
代码示例:
public void nextPermutation(int[] nums) {
int i = nums.length - 2;
while (i >= 0 && nums[i] >= nums[i + 1]) {
i--;
}
if (i >= 0) {
int j = nums.length - 1;
while (j >= 0 && nums[i] >= nums[j]) {
j--;
}
swap(nums, i, j);
}
reverse(nums, i + 1);
}
public void swap(int[] nums, int i, int j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
public void reverse(int[] nums, int start) {
int left = start, right = nums.length - 1;
while (left < right) {
swap(nums, left, right);
left++;
right--;
}
}