【算法題】全排列,字典序

參考

全排列:


/*
 * 遞歸輸出序列的全排列
 */
void FullArray(char* array, size_t array_size, unsigned int index)
{
    if(index >= array_size)
    {
        for(unsigned int i = 0; i < array_size; ++i)
        {
            cout << array[i] << ' ';
        }

        cout << '\n';

        return;
    }

    for(unsigned int i = index; i < array_size; ++i)
    {
        swap(array, i, index);

        FullArray1(array, array_size, index + 1);

        swap(array, i, index);
    }
}

字典序:


使用字典序輸出全排列的思路是,首先輸出字典序最小的排列,然後輸出字典序次小的排列,……,最後輸出字典序最大的排列。這裏就涉及到一個問題,對於一個已知排列,如何求出其字典序中的下一個排列。這裏給出算法。

  • 對於排列a[1…n],找到所有滿足a[k]<a[k+1](0<k<n-1)的k的最大值,如果這樣的k不存在,則說明當前排列已經是a的所有排列中字典序最大者,所有排列輸出完畢。

  • 在a[k+1…n]中,尋找滿足這樣條件的元素l,使得在所有a[l]>a[k]的元素中,a[l]取得最小值。也就是說a[l]>a[k],但是小於所有其他大於a[k]的元素,如果有相同的a[l],取最後的一個
    交換a[l]與a[k].

  • 對於a[k+1…n],反轉該區間內元素的順序。也就是說a[k+1]與a[n]交換,a[k+2]與a[n-1]交換,……,這樣就得到了a[1…n]在字典序中的下一個排列。

這裏我們以排列a[1…8]=13876542爲例,來解釋一下上述算法。首先我們發現,1(38)76542,括號位置是第一處滿足a[k]<a[k+1]的位置,此時k=2。所以我們在a[3…8]的區間內尋找比a[2]=3大的最小元素,找到a[7]=4滿足條件,交換a[2]和a[7]得到新排列14876532,對於此排列的3~8區間,反轉該區間的元素,將a[3]-a[8],a[4]-a[7],a[5]-a[6]分別交換,就得到了13876542字典序的下一個元素14235678。下面是該算法的實現代碼


#include <iostream>
#include <vector>
#include <limits.h>
#include <algorithm>

using namespace std;


vector<int> NextDic(vector<int>& vec)
{
    vector<int> next(vec);
    int last_(0);

    for (int i = next.size()-1; i >= 1;--i)
    {
        if (vec[i] > vec[i - 1])
        {
            last_ = i-1;
            break;
        }
    }

    if (last_ == 0&&vec[last_]>=vec[last_+1])
    {
        next.clear();
        return next;
    }
    int first_big_index(last_+1);
    for (auto i = first_big_index; i < vec.size();++i)
    {
        if (vec[i]>vec[last_]&& vec[i]<=vec[first_big_index] )
        {
            first_big_index = i;
        }
    }
    swap(next[last_], next[first_big_index]);
    int left = last_ + 1, right = next.size() - 1;
    while (left <right)
    {
        swap(next[left], next[right]);
        left++;
        right--;
    }

    return next;
}
void func(vector<int> & vec)
{
    sort(vec.begin(), vec.end());
    vector<int> next = vec;
    while (!next.empty())
    {
        for (auto i = 0; i < next.size();++i)
        {
            cout << next[i] << " ";
        }
        cout << endl;
        next = NextDic(next);
    }
}

int main()
{
    vector<int> vec{ 2, 1, 2 };
    func(vec);
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章