LintCode 190: Next Permutation

LintCode 190: Next Permutation

題目描述

給定一個若干整數的排列,給出按正數大小進行字典序從小到大排序後的下一個排列。c++

若是沒有下一個排列,則輸出字典序最小的序列。數組

樣例code

左邊是原始排列,右邊是對應的下一個排列。排序

1,2,3 → 1,3,2

3,2,1 → 1,2,3

1,1,5 → 1,5,1

Fri Feb 24 2017

思路

先看一個例子:it

8, 5, 3, 7, 6, 5, 4, 1

下一個排列應該是:io

8, 5, 4, 1, 3, 5, 6, 7

看起來應該是要從後往前找,找到第一個降序的數字,由於若是一直都是升序的話,說明這一部分以及是全排列的最大狀況了。第一個比它後一個數小的數,就是須要替換爲比他大一點的那個數。在上面的例子中就是3.class

找到3之後,須要把它替換成一個比它大一點的數,因而再從後往前找,找到第一個比它大的數,在上面的例子中,就是4左邊是原始排列,右邊是對應的下一個排列。next

34交換,因爲後半部分剛纔已是最大的全排列了,因此須要翻轉一下,變成最小的全排列。co

整個過程大概以下:字典

8, 5, 3, 7, 6, 5, 4, 1

8, 5, 3, 7, 6, 5, 4, 1

8, 5, 3, 7, 6, 5, 4, 1

8, 5, 4, 7, 6, 5, 3, 1

8, 5, 4, 7, 6, 5, 3, 1

8, 5, 4, 1, 3, 5, 6, 7

考慮一些特殊狀況,若數組長度小於等於1,則下一個排列就是它自己,因此直接返回。

若數組自己就是最大的全排列,則在第一次從前日後尋找第一個比它後一個數小的數時,找到最前面也找不到,因而就不須要找第二個數了,直接將整個數組翻轉就行了。

代碼

// 下一個排列
void nextPermutation(vector<int> &nums)
{
    if (nums.size() <= 1) return;
    vector<int>::iterator l = nums.end() - 2;
    for (; l >= nums.begin(); --l)
        if (*l < *(l + 1)) break;
    if (l >= nums.begin())
    {
        vector<int>::iterator r = nums.end() - 1;
        for (; r != l; --r)
            if (*r > *l) break;
        swap(*l, *r);
    }
    reverse(l + 1, nums.end());
}
相關文章
相關標籤/搜索