[LeetCode] - 31.Next Permutation - java

LeetCode 31.Next Permutation

问题描述
Tags: Array
Difficlty: Medium
Description:
Implement next permutation, which rearranges numbers into the lexicographically
next greater permutation of numbers.
If such arrangement is not possible, it must rearrange it as the lowest possible order (ie, sorted in ascending order).
The replacement must be in-place, do not allocate extra memory.
Here are some examples. Inputs are in the left-hand column and its corresponding outputs are in the right-hand column.
* 1,2,3 → 1,3,2
* 3,2,1 → 1,2,3
* 1,1,5 → 1,5,1

问题:输入一个数组序列,返回它在字典序列中的下一个序列。字典序和全排列理解
理解和思路
1. 如何判断一个序列a[0,1,2,…,n-1]是否还有下一个序列?
- 从前向后,查看否有两个数字组成顺序(或者从后向前看,是否有两个数组成逆序);
- 从后向前找,找到最后一个满足a[k] < a[k+1]的下标k。
2. 如何找到下一个序列?
* 根据字典序,位置[k]处发生变化,变化来的新数,是从a[k+1,..,n-1]大于a[k]的最小数;
* 在a[k+1,..,n-1]都是逆序,要使新序列和原始序列紧挨着,就需要把a[k+1,..,n-1]反转;
3. 如果所找到的k==-1,也就是说是字典序中的最后一个序列了,把整个序列反转,得到字典序中的第一个序列。

public void nextPermutation(int[] nums) {
    // 找到K值
    // 从前向后找到最后的两个顺序数字,比较麻烦,需要比较不同的k值,这个过程等价于,从后向前找,找到第一组逆序的数
    int k  = nums.length - 2;
    while( k >= 0 ){
        if(nums[k] < nums[k+1]){ break; }
         k--;
    }
    //如果k==-1了,还没有逆序,就说明是最后一个序列,那就整个进行翻转,形成最开始的序列
    if(k < 0){
        reverse(nums, 0);
        return;
    }
    // 在a[k+1]~a[n-1]之间找到大于a[k]的最小的数
    // 因为a[k+1]~a[n-1]这一段从后向前是顺序,所以从后向前遍历,找到第一个大于a[k]的数的下标
    // a[k+1]~a[n-1]都是降序排列,所以第一个大于a[k]的数,就是最接近a[k]的数
    if(k >= 0){
        int j =nums.length-1;
        while(j>= k+1 && nums[j] <= nums[k]){ j--; }
        swap(nums, k, j);
    }
    //再对a[k+1]~a[n-1]进行翻转
    reverse(nums,k+1);
}

private void reverse(int[] nums, int start) {
    int i = start, j = nums.length - 1;
    while (i < j) {
        swap(nums, i, j);
        i++;
        j--;
    }
}

private void swap(int[] nums, int i, int j) {
    int temp = nums[i];
    nums[i] = nums[j];
    nums[j] = temp;
}

猜你喜欢

转载自blog.csdn.net/smj19920225/article/details/80236665