31. Next Permutation

来源:互联网 发布:时雨改二数据 编辑:程序博客网 时间:2024/06/05 14:24

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

找到数字的排列组合中,下一个比当前大的第一组合,如果没有,则返回最小的组合。

本题也可以暴力搜索实现,即将数组中的左右组合全部得出来,然后与给出的组合进行比对,如果刚好为下一个大一点的,则返回。该方法会TimeOut,因为数组长度为n的排列组合有n!个,如果n = 1000,则上百万了,所以时间开销较大。

另一种方法就是分析规律,当前排列组合的下一个较大的,其实就是找到第一个相邻的逆序对,假设为i,i+1(i, i + 1 < 数组长度length),再从i+1, length之间找到第一个大于a[i]的位置j,将i, j位置的数组值交换,再将i后面(不含i)的数反转即可。

如下:

class Solution {    public void reverseArray(int[] nums, int left, int right){        for (int i = left; i < nums.length&&i <= right; ++ i){            int tmp = nums[i];            nums[i] = nums[right];            nums[right--] = tmp;        }    }        public void swapVal(int[] nums, int i, int j){        int tmp = nums[i];        nums[i] = nums[j];        nums[j] = tmp;    }        public void nextPermutation(int[] nums) {        if (nums.length <= 1){            return;        }        int right = nums.length - 1;        while (right >= 1&&nums[right-1] >= nums[right]){            right --;        }        if (right != 0){            right --;        }        else {            reverseArray(nums, 0, nums.length - 1);            return;        }        int index = nums.length - 1;        while (index >= 1&&nums[index] <= nums[right]){            index--;        }        swapVal(nums, right, index);        reverseArray(nums, right+1, nums.length - 1);    }}