LeetCode031-Next Permutation-

Next Permutation

Question:

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 and use only constant 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,31,3,2
3,2,11,2,3
1,1,51,5,1

解法代碼

import java.util.Arrays;

public class LeetCode31 {

    public static void main(String[] args) {
        int[] nums = new int[]{1, 2, 3};
        System.out.print("Array string : " + Arrays.toString(nums));
        new LeetCode31().nextPermutation(nums);
        System.out.println(",nextPermutation: " + Arrays.toString(nums));
        nums = new int[]{3, 2, 1};
        System.out.print("Array string : " + Arrays.toString(nums));
        new LeetCode31().nextPermutation(nums);
        System.out.println(",nextPermutation: " + Arrays.toString(nums));
        nums = new int[]{1, 1, 5};
        System.out.print("Array string : " + Arrays.toString(nums));
        new LeetCode31().nextPermutation(nums);
        System.out.println(",nextPermutation: " + Arrays.toString(nums));
        nums = new int[]{5, 3, 4, 2, 1};
        System.out.print("Array string : " + Arrays.toString(nums));
        new LeetCode31().nextPermutation(nums);
        System.out.println(",nextPermutation: " + Arrays.toString(nums));
        nums = new int[]{1, 3, 2};
        System.out.print("Array string : " + Arrays.toString(nums));
        new LeetCode31().nextPermutation(nums);
        System.out.println(",nextPermutation: " + Arrays.toString(nums));
        nums = new int[]{4, 2, 0, 2, 3, 2, 0};
        System.out.print("Array string : " + Arrays.toString(nums));
        new LeetCode31().nextPermutation(nums);
        System.out.println(",nextPermutation: " + Arrays.toString(nums));
        nums = new int[]{2, 2, 3, 4, 2, 3, 1, 1, 2};
        System.out.print("Array string : " + Arrays.toString(nums));
        new LeetCode31().nextPermutation(nums);
        System.out.println(",nextPermutation: " + Arrays.toString(nums));
        nums = new int[]{1, 1};
        System.out.print("Array string : " + Arrays.toString(nums));
        new LeetCode31().nextPermutation(nums);
        System.out.println(",nextPermutation: " + Arrays.toString(nums));
    }
    
    public void nextPermutation(int[] nums) {
        // 空數(shù)組和只有一個元素的數(shù)組宏邮,直接返回
        if(nums == null || nums.length < 2) {
            return;
        }
        int i = nums.length - 2;
        // 從后往前找侍匙,數(shù)據(jù)增大則跳過伏恐,如果發(fā)現(xiàn)數(shù)據(jù)變小米苹,則說明找到了更大的排列
        while(i >= 0 && nums[i] >= nums[i + 1]) {
            i--;
        }
        // If such arrangement is not possible, 
        // it must rearrange it as the lowest possible order
        // 沒有找到解,元素全部反轉(zhuǎn)
        if(i == -1) {
            reverse(nums, 0);
            return;
        }
        int j = i + 1;
        // 因為i后面的元素是有序的,利用反轉(zhuǎn)對i后面的元素進行排序
        reverse(nums, j);
        // 找到數(shù)據(jù)交換的位置
        while(nums[j] <= nums[i]) {
            j++;
        }
        swap(nums, i, j);
    }
    
    private void reverse(int[] nums , int start) {
        int i = start;
        int j = nums.length - 1;
        while(i < j) {
            swap(nums, i, j);
            i++;
            j--;
        }
    }
    private void swap(int[] nums, int i, int j) {
        int tmp = nums[i];
        nums[i] = nums[j];
        nums[j] = tmp;
    }
}

Output:

Array string : [1, 2, 3],nextPermutation: [1, 3, 2]
Array string : [3, 2, 1],nextPermutation: [1, 2, 3]
Array string : [1, 1, 5],nextPermutation: [1, 5, 1]
Array string : [5, 3, 4, 2, 1],nextPermutation: [5, 4, 1, 2, 3]
Array string : [1, 3, 2],nextPermutation: [2, 1, 3]
Array string : [4, 2, 0, 2, 3, 2, 0],nextPermutation: [4, 2, 0, 3, 0, 2, 2]
Array string : [2, 2, 3, 4, 2, 3, 1, 1, 2],nextPermutation: [2, 2, 3, 4, 2, 3, 1, 2, 1]
Array string : [1, 1],nextPermutation: [1, 1]

Time And Space Complexity

Time: O(n) 在最壞的情況下,只需要對整個數(shù)組進行兩次掃描
Space:O(1) 不需要使用額外的存儲空間薄湿,原地替換

Tips

關(guān)鍵點:

  • 從后往前遍歷元素,如果元素是增大或者相等的則跳過偷卧,如果出現(xiàn)一個變小的元素則說明豺瘤,這個就是解的位置,假定為index涯冠,如下圖(圖中index的值為i-1):


  • 如果全部元素遍歷完炉奴,都是遞增或者是相等的,則說明沒有更小排列蛇更,反轉(zhuǎn)數(shù)組瞻赶,直接返回

  • 對數(shù)組index后的元素進行遞增排序,即對原數(shù)組index后的元素做反轉(zhuǎn)

  • 在index后尋找第一個大于第index處的元素派任,與index位置的元素交換

求解過程可以參考下圖砸逊,下圖中第三步與第四步交換了次序:

/**
  *  一開始耍群,不太優(yōu)雅的實現(xiàn)代碼罢绽,供反思
  */
public void nextPermutation(int[] nums) {
        // 空數(shù)組和只有一個元素的數(shù)組,直接返回
        if(nums == null || nums.length < 2) {
            return;
        }
        // 用于標記是否只需要重新排序即可
        boolean flag = false;
        // 數(shù)據(jù)交換點
        int index = nums.length - 1;
        // 從后往前找类早,數(shù)據(jù)增大則跳過豆混,如果發(fā)現(xiàn)數(shù)據(jù)變小篓像,則說明找到了更大的排列
        for(int i = index - 1; i >= 0; i--) {
            if(nums[i] > nums[i + 1]) {
                if(i == 0) {
                    flag = true;
                }
            }
            // 找到更大的排列
            if(nums[i] < nums[i + 1]){
                index = i;
                break;
            }
        }
        if(flag) {
            //If such arrangement is not possible, 
            //it must rearrange it as the lowest possible order
            Arrays.sort(nums);
            return;
        }
        if(nums.length - index > 1) {
            Arrays.sort(nums, index + 1, nums.length);
        }
        for(int j = index + 1; j < nums.length; j++) {
            if(nums[j] > nums[index]) {
                int tmp = nums[index];
                nums[index] = nums[j];
                nums[j] = tmp;
                break;
            }
        }
        
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市皿伺,隨后出現(xiàn)的幾起案子员辩,更是在濱河造成了極大的恐慌,老刑警劉巖鸵鸥,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件奠滑,死亡現(xiàn)場離奇詭異,居然都是意外死亡妒穴,警方通過查閱死者的電腦和手機宋税,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來讼油,“玉大人杰赛,你說我怎么就攤上這事“ǎ” “怎么了乏屯?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵阔墩,是天一觀的道長。 經(jīng)常有香客問我瓶珊,道長,這世上最難降的妖魔是什么耸彪? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任伞芹,我火速辦了婚禮,結(jié)果婚禮上蝉娜,老公的妹妹穿的比我還像新娘唱较。我一直安慰自己,他們只是感情好召川,可當我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布南缓。 她就那樣靜靜地躺著,像睡著了一般荧呐。 火紅的嫁衣襯著肌膚如雪汉形。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天倍阐,我揣著相機與錄音概疆,去河邊找鬼。 笑死峰搪,一個胖子當著我的面吹牛岔冀,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播概耻,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼使套,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了鞠柄?” 一聲冷哼從身側(cè)響起侦高,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎春锋,沒想到半個月后矫膨,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡期奔,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年侧馅,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片呐萌。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡馁痴,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出肺孤,到底是詐尸還是另有隱情罗晕,我是刑警寧澤济欢,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站小渊,受9級特大地震影響法褥,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜酬屉,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一半等、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧呐萨,春花似錦杀饵、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至惨远,卻和暖如春谜悟,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背锨络。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工赌躺, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人羡儿。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓礼患,卻偏偏與公主長得像,于是被迫代替她去往敵國和親掠归。 傳聞我的和親對象是個殘疾皇子缅叠,可洞房花燭夜當晚...
    茶點故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內(nèi)容