Next Permutation-leetcode下一個排列組合

問題描述:
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

STL源碼剖析>>page:380對此問題有詳盡描述,相當於實現算法裏面的next_permutation()函數,與之對應的另一個函數是prev_permutation()

這裏在自己擼一下思路:

什麼是下一個全排數列,如abc的下一個是acb,就是按照字典的搜索順序排列

以數組{1,2,4,6,5,3}爲例

下一個排列和當前排列應該具有儘可能長的公共前綴,所以從數組後面後向推算

從3開始找,{3}只有一個數,所以無下一個全排

繼續看{5,3}無下一個全排

{6,5,3}無下一個全排

也就是說,如果序列是有序並且是降序時無下一個全排

那我們從後向前找到降序數列和無序數列的分界線,即4和6那兒即可

怎麼找?從後向前,比較相鄰的元素,直到找到前小後大的

注:如果一直遍歷到1的位置都沒有找到,說明此序列爲全遞減的(按照題意,將其逆序即可)

此時,1,2已經是兩個序列的公共前綴,也就是說,我們只要找到{4,6,5,3}的下一個排列即可

怎麼找?4653是這四個數字組合中4開頭的數字中最大的那個,我們需要從653中找到剛好比4大的數字,即5,

讓5和4交換數列變成了5643,那隻要找到以5開頭的數的最小排列即可

怎麼找?可以發現5後邊的643是降序的,那隻要讓643爲346逆序即可

{1,2,4,6,5,3}的下一個排列爲{1,2,5,3,4,6}

再將上面的思路具體化一下:

  • 讓兩個指針pi和pi_front分別指向數列的倒數第一個和倒數第二個

  • 從後向前遍歷兩兩比較,找到前小後大的一對,此時pi指向大的(6),pi_front指向小的(4)

  • 用 j 重新從後向前遍歷,直到找到比pi_front大的數,交換 j 和pi_f的值

  • 把pi_f後面的所有數全部反轉

  • 進行判斷,如果整個序列爲降序,那麼反轉所有的元素

代碼如下:

bool NextPermutation(int *start,int *end)//[start,end)
{
    assert(start != NULL && end != NULL);
    int* pi = start;
    if(pi == end || ++pi == end)//只有一個元素時
        return false;
    pi = end;
    --pi;
    int* pi_front = --pi;
    ++pi;
    while(*pi < *pi_front)
    {
        --pi;
        --pi_front;
    }
    int* j = end;
    while(*--j < *pi_front);

    iter_swap(pi_front,j);
    reverse(pi,end);
    return true;
    if(pi_front == start)//全遞增數列,全部逆序
    {
        reverse(start,end);
        return false;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章