31.Next Permutation
给定一个数组,将里面的数字找到比当前排列大一个的下一个排列。如果找不到,则返回最小值排列。
1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1
注意:是找比当前排列大的下一个排列,并不是找最大的排列。
思路:
规律还是比较好找的,从后往前看,如果是:54321. 这种表示已经是最大排列了,因为前面一个数都比后面一个数大,不管怎么换,所组成的排列都比当前的数小。而只有 54231,这种,后面的3有比前面的2大,将大的数字换过来,整体排列就变大了。所以,关键在于从后往前看,找到第一个前面比后面小的数,然后,从后面的数里面选一个比当前位置的数大的交换,然后将后面的数字从小到大排列。
比如: 12543, 2比5小,然后在后面的543中找一个比2大的数交换,找到了3,变成13542,最后再将542从小到大排列,即为:13245。即,13245是比12543大的下一个排列。
class Solution { public: void nextPermutation(vector<int>& nums) { int n = nums.size(), r = n - 1; for (int i = n - 1; i > 0; i--) { if (nums[i - 1] >= nums[i]) continue; else { //寻找位置 while (r > i - 1) { if (nums[i - 1] < nums[r]) { //再后面寻找比当前大的数交换 int tmp = nums[i - 1]; nums[i - 1] = nums[r]; nums[r] = tmp; break; } else r--; } minToMax(nums, i, n - 1);//后面剩余的从小到大排列 return; } } minToMax(nums, 0, n - 1); } void minToMax(vector<int>& nums, int left, int right) { // 从小到大交换 int n = right - left + 1, tmp = 0; for (int i = 0; i < n / 2; i++) { tmp = nums[i + left]; nums[i + left] = nums[right - i]; nums[right - i] = tmp; } } };
Java 版:
class Solution { public void nextPermutation(int[] nums) { for(int i = nums.length - 1; i > 0; i--){ if(nums[i] > nums[i-1]){ for(int j = nums.length - 1; j >= i ; j--){ // 要注意这儿 j >= i if(nums[j] > nums[i-1]){ int tmp = nums[i-1]; //交换数字 nums[i-1] = nums[j]; nums[j] = tmp; Arrays.sort(nums,i,nums.length); // 对后面的数字按升序重排列 return; //直接退出 } } } } Arrays.sort(nums); //因为有上面的 return 存在,如果还执行到这儿,说明数字已经达到最大,重排一下即可 } }