本题代码来自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]<nums[i+1]*/ /*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; } }