31. 下一个排列
实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。
如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。
必须原地修改,只允许使用额外常数空间。
以下是一些例子,输入位于左侧列,其相应输出位于右侧列。
1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,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 }
浙公网安备 33010602011771号