31. 下一个排列

实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。

如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。

必须原地修改,只允许使用额外常数空间。

以下是一些例子,输入位于左侧列,其相应输出位于右侧列。
1,2,31,3,2
3,2,11,2,3
1,1,51,5,1

 

思路:查找该排序在全排序的下一个序列,即在全排序的升序中,比该排序数值大且相邻的排序。 (全排列参考46题)

目的是把后面的「大数」与前面的「小数」交换,且增加的幅度尽可能的小。

详见https://leetcode-cn.com/problems/next-permutation/solution/xia-yi-ge-pai-lie-suan-fa-xiang-jie-si-lu-tui-dao-/

 1     public void nextPermutation(int[] nums) {
 2         if (nums == null || nums.length < 2) return;
 3         //从末尾开始逐次向前查找,一直找到相邻位置的数字为升序的地方
 4         //即3421中,34的位置
 5         int i = nums.length - 2;
 6         while (i >= 0 && nums[i] >= nums[i + 1]) {
 7             i--;
 8         }
 9 
10         if (i >= 0) {
11             //找到第一个升序位置,则同时说明,从i+1开始数组全为降序
12             //再次从后向前查找,在[i+1,end),找到第一个比nums[i]大的值,互相交换
13             //即完成后面的「大数」与前面的「小数」交换,且增加的幅度尽可能的小
14             //最后将i+1开始的数组转为升序
15             int j = nums.length - 1;
16             while (j > i && nums[j] <= nums[i]) {
17                 j--;
18             }
19             swap(nums, i, j);
20             reverse(nums, i + 1);
21         } else {
22             //当数组遍历完,则说明,全数组为降序,则为最大值
23             //将全数组倒置,则为最小排序
24             reverse(nums, 0);
25         }
26 
27     }
28     //倒置
29     private void reverse(int[] nums, int start) {
30         int i = start;
31         int j = nums.length - 1;
32         while (i < j) {
33             swap(nums, i, j);
34             i++;
35             j--;
36         }
37     }
38     //交换
39     private void swap(int[] nums, int x, int y) {
40         int temp = nums[x];
41         nums[x] = nums[y];
42         nums[y] = temp;
43     }

 

posted @ 2020-07-22 10:49  陈糊糊啊  阅读(123)  评论(0)    收藏  举报