代码重构:leetcode 31. 下一个排列

259 阅读1分钟

31. 下一个排列

下一个排列,可以说是下一个更大的数。

怎么找下一个更大的数呢,实际上就是找最后一个存在逆序的元素i,此时把之前和之后分成两片,需要找打之后那一片里面第一个大于i的数字和i交换,然后将下一片升序排序。

如何获得呢?其实就是从后往前找,找到第一个i使得nums[i]<nums[i+1]。此时我们知道,i之后的那一片一定是降序的。

于是我们可以用二分查找,加上替换,以及倒转下一片来求解。

但需要注意的是,java里面的Arrays.binarySearch查找是只能查找升序的,所以我们可以先倒转下一片成升序,然后再使用类库。

或者是我们直接写一个类库求降序的数组。

    public void nextPermutation(int[] nums) {
        int i = nums.length - 2;
        for (; i >= 0; i--) {
            if (nums[i] < nums[i + 1]) break;
        }
        if (i == -1) {
            trans(nums, 0, nums.length - 1);
            return;
        }
        int t = binarySearch1(nums, i + 1, nums.length, nums[i]);
        //也可以使用Arrays. binarySearch(nums, i + 1, nums.length, nums[i]),但得先
        // swap(nums, i, t);
        if (t < 0) t = -t - 1;
        else {
            while (nums[t] == nums[i]) t--;
        }
        swap(nums, i, t);
        trans(nums, i + 1, nums.length - 1);
    }
	
	//这样写,如果找不到,一定左右互易
    public int binarySearch1(int[] nums, int low, int high, int target) {
        high = high - 1;
        while (low <= high) {
            int mid = (low + high) >>> 1;
            if (nums[mid] < target) high = mid - 1;
            else if (nums[mid] == target) return mid;
            else low = mid + 1;
        }
        return -(high + 1);
    }

    public void swap(int[] nums, int s0, int s1) {
        int temp = nums[s0];
        nums[s0] = nums[s1];
        nums[s1] = temp;
    }

    public void trans(int[] nums, int from, int to) {
        while (from < to) {
            swap(nums, from++, to--);
        }
    }