Next Permutation

題目描述

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

分析思路

首先,我們來看一個簡單的例子
比如158476531這個序列,我們如果只想它變大一點點,應該儘可能的不去增加高位。因爲增加高位會帶來更大的增益。所以對於一個長爲n的序列,我們增加第n位的前提是,前n-1位已經達到了最大排列方法。所以我們從後往前看

1
31
531
6531
76531

上邊列舉的都是一個升序的序列,不可能變得更大了,先不動它。
然後,可以將4移到後面來來增大。但是問題在於,把誰移到4的位置。因爲是找下一個數,所以我們要找一個比4小卻儘可能大的數,所以找到5,交換變成576431。
把5換到4的位置後,後幾位(76431)仍然是個降序的排列,要做成一個以5開頭最小的序列,而這個序列應該是升序的,所以我們直接把76431倒置一下,就從降序變成升序了。
下面是一個找next permutation的動畫:
這裏寫圖片描述

代碼

public void nextPermutation(int[] nums) {
        if (nums.length <= 1) {
            return;
        }
        int i = nums.length - 2;
        // 找到第一個下降點,我們要把這個下降點的值增加一點點
        //511特殊,要加=,下邊同理
        while (i >= 0 && nums[i] >= nums[i + 1]) {
            i--;
        }
        // 如果這個下降點還在數組內,我們找到一個比它稍微大一點的數替換       
        if (i >= 0) {
            int j = nums.length - 1;
            while (j > i && nums[j] <= nums[i]) {
                j--;
            }
            swap(nums, i, j);
        }
        // 如果在之外,說明整個數組是降序的,是全局最大了
        // 將下降點之前的部分倒序構成一個最小序列
        reverse(nums, i + 1, nums.length - 1);
    }

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

    private void reverse(int[] nums, int left, int right) {
        while (left < right) {
            swap(nums, left, right);
            left++;
            right--;
        }
    }
發佈了113 篇原創文章 · 獲贊 19 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章