版权声明:本文为博主原创,未经允许请不要转载哦 https://blog.csdn.net/weixin_43277507/article/details/88135798
9、下一个排列
题设要求:实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。
如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)
必须原地修改,只允许使用额外常数空间。
思路:理解题意,寻找手动算法的原理
(1)从数组最后一个元素开始扫描,寻找到nums[i] > nums[i - 1]的第一个i值。
(2)如果得到i值大于等于1,说明数组存在下一个排列。
a.我们还是从数组最后一个元素开始扫描,寻找到num[j] > nums[i - 1]的第一个j值。由于nums[i] > nums[i - 1],所以我们的j值一定是大于等于i的。
b.交换索引为i - 1和索引为j的元素的值。
c.此时索引i及之后的排列时一个降序排列,将其变成升序排列即可。
为什么说此时索引i及之后的排列是一个降序排列呢?
对于原来的数组,由于我们是从数组最后一个元素开始扫描寻找到的nums[i] > nums[i - 1]的第一个i值,我们原数组中i之后的排列一定是一个降序排列。那么我们只需要看交换之后是否依然是一个降序排列呢?
而寻找索引j,我们还是从数组最后一个元素开始扫描,寻找到num[j] > nums[i - 1]的第一个j值。对于索引j之后的值,一定是小于等于nums[i - 1]的。对于而对于索引i到j - 1这部分元素,一定是大于等于num[j]的,自然一定大于nums[i - 1],那么,交换之后,原数组中i之后的排列一定依然是一个降序排列。
(3)如果得到的i值小于1,说明数组不存在下一个排列,倒序输出数组即得升序排列
分析:
代码如下:
public class Solution{
public static void main(String[] args)
{
Solution sl = new Solution();
int[] nums= {1,4,3,2};
int len=nums.length;
sl.nextPermutation(nums);
for(int i=0;i<len;i++)
{
System.out.print(nums[i]);
}
}
public void nextPermutation(int[] nums) {
int n = nums.length;
int i = n - 1;
for(; i >= 1; i--) {
if(nums[i] > nums[i - 1]) {
break;
}
}
if(i >= 1) {
int j = n - 1;
for(; j >= i; j--) {
if(nums[j] > nums[i - 1]) {
break;
}
}
swap(i - 1, j, nums);
reverse(nums, i);
}else {
reverse(nums, 0);
}
}
private void reverse(int[] nums, int index) {
int i = index;
int j = nums.length - 1;
while(i < j) {
swap(i, j, nums);
i++;
j--;
}
}
private void swap(int i, int j, int[] nums) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}