每日一题.31. 下一个排列

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

我的解法:要将给定数字序列重新排列成字典序中下一个更大的排列,目的是找一个比当前数字大且尽可能小的数,只需将数字序列后面的大数与前面的小数交换。首先从右往左查找打破升序规律的下标i,从左往右看[i+1, len)为降序序列;然后在[i+1,len)中找到比nums[i]大的最小数nums[j],并交换nums[j]和nums[i],交换后[i+1, len)仍为降序序列,最后一步是将[i+1, len)翻转成升序序列,即可得到比当前数字大且尽可能小的数。

时间复杂度:O(n),空间复杂度:O(1)

class Solution {
    public void nextPermutation(int[] nums) {
        int len = nums.length, i, j, temp;
        /*从右往左查找打破升序的点i, [i+1,len)为降序序列*/
        for (i = len - 2; i >= 0; i--) {
            if (nums[i] < nums[i+1]) break;
        }
        /*若点i为-1, 说明整个序列是降序序列, 直接翻转*/
        if (i == -1) {
            Arrays.sort(nums);
            return;
        }
        /*查找[i+1, len)比nums[i]大的最小元素*/
        for (j = len - 1; j > i; j--) {
            /*找到比nums[i]大的最小元素后交换*/
            if (nums[j] > nums[i]) {
                temp = nums[j];
                nums[j] = nums[i];
                nums[i] = temp;
                break;
            }
        }
        /*交换后[i+1,len)仍为降序序列, 翻转[i+1,len)使其变成升序*/
        Arrays.sort(nums, i+1, len);
    }
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容