本题代码来自Leetcode官方,个人对其理解后,生成自己的注解,以便更好的让读者理解。如有侵权,立即删除!
public class Main31 { public static void main(String[] args) {
int[] arr = new int[]{9, 5, 3, 1};
nextPermutation(arr);
} /**
* 核心思想:给定一个降序则该序列没有可能有下一个更大的排列;
* 1.从给定数组的右侧扫描出第一个a[i-1]<a[i]; (违背了核心思想,所以处理)
* 2.对a[i-1]固定位置,从其右侧(从右到左)找出第一个比a[i-1]大的数字a[j];
* 3.交换a[i-1]和a[j]的值。此时a[i-1]位置是下一个更大元素的首位,也是未交换之前a[i-1]到右侧最后一位组成数的下一个比起大的数的首位;
* 4.将a[i-1]右侧重新排列为最小(升序,之前的降序);此时,构成的数是原数下一个比其大的数;
* @param nums
*/
public static void nextPermutation(int[] nums) {
int i = nums.length-1; //倒数第1个元素下标 while(i-1 >= 0 && nums[i] <= nums[i-1]){ /*确定nums[i-1]的位置,即nums[i-1]<nums[i],简化为确定i-1的位置*/
i--;
}
if(i-1 >= 0){ /*如果i位置还在数组中,即nums[i-1]<nums[i]*/ /*i不在数组的情况就是遇到了一降序数组,直接反转让其成一个最小数列*/
int j = nums.length-1; /*定位j到i的右侧区域的最右侧*/
while(j >= 0 && nums[j] <= nums[i-1]){ /*找到nums[j]第一次大于nums[i-1]的位置,此时要满足j也要在数组中(当然,j肯定在数组中)*/
j--; /*j停下来的位置就是第一次大于nums[i-1]的位置*/
}
swap(nums,i-1,j); /*交换nums[i-1],nums[j]的值*/
}
reverse(nums,i); /*反转i右侧的降序,转变为升序*/
} private static void reverse(int[] nums, int start) {
int i = start;
int j = nums.length-1;
while (i < j){
swap(nums,i,j);
i++;
j--;
}
} private static void swap(int[] nums, int i, int j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}