下个排列
题目来源:下个排列
问题描述:
问题分析:
根据题目及案例分析:
(1). 当数组只有一个数或零个数时数组无法修改
(2).当数组是降序排列时(此时该数字序列为最大) 只需要将数组反转即可转化为最小情况
( 3 ).如果数组的排列非降序 ,则需要将数组重新排列,变为更大的数字序列(更大序列不是任意大,这里可以理解为 将整个数字序列进行全排列,所组成数字按大小降序排列,正好是当前数字序列对应的索引的前一个)
解决办法:
1 . 将一个数字序列从后往前遍历,找到一个降序的数字 , 例如 arr = { 1 , 3 , 2 } , 则 第一个降序的数字即为 n = 1 , 记录索引 index
2 . 从 index 开始向后找比 n 大的最小数 m , 即 2
3 . 将 n 和 m 交换位置 ( 因为 n 是 从后往前遍历的 第一个降序的数 , 所以 n 以后的数 从前往后遍历 是降序排列的 ) 而 m 是 比 n 的大的最小数 , 所以交换位置后 后面的序列 仍然是个降序序列 即 { 2 , 3 , 1 }
4 . 将后面的降序序列 , 反转 则后续序列变为最小值 即 { 2 , 1 , 3 } , 这么原因是: m和n交换是最低能改变的进位, 而后面是降序排列即该序列的最大值, 由于进位已经增大 所有后面的序列需要变成最小值才能符合条件(3)
代码实现:
//leetcode submit region begin(Prohibit modification and deletion)
class Solution {
public void nextPermutation(int[] nums) {
//小于2个元素
if (nums.length < 2) {
return;
}
//只有两个元素时
if (nums.length == 2) {
int temp = nums[0];
nums[0] = nums[1];
nums[1] = temp;
return;
}
boolean flag = true;
int smaller = 0;
for (int i = nums.length - 1; i > 0; i--) {
if (nums[i - 1] >= nums[i] && flag) {
continue;
} else {
flag = false;
samller = i - 1;
break;
}
}
int bigger = smaller;
for (int i = simller + 1; i < nums.length; i++) {
if (nums[i] > nums[smaller]) {
if (bigger == smaller || nums[bigger] >= nums[i]) {
bigger = i;
}
}
}
if (flag){
reverse(nums,0,nums.length-1);
}else {
swap(nums,bigger,smaller);
reverse(nums,smaller+1,nums.length-1);
}
}
public static void reverse(int[] nums, int a, int b) {
int l = a, r = b;
while (l < r) {
swap(nums, l++, r--);
}
}
public static void swap(int[] nums, int a, int b) {
int c = nums[a];
nums[a] = nums[b];
nums[b] = c;
}
}
//leetcode submit region end(Prohibit modification and deletion)