演算法 全排列問題 字典序法

2022-08-19 00:40:07 字數 1260 閱讀 8689

求乙個排列的下乙個排列我們有暴力的n進制法,當然也就有效率較高的字典序法。

洛谷1088 火星人

題目描述

求排列a[1],a[2],a[3],……,a[n]之後的第m個全排列。

輸入格式

共三行。

第一行乙個正整數n(1 <= n <= 10000)。

第二行乙個正整數m(1 <= n <= 100)。

下一行是1到n這n個整數的乙個排列,用空格隔開。

輸出格式

n個整數,表示第m個全排列。每兩個相鄰的數中間用乙個空格分開。

輸入輸出樣例

輸入

5

31 2 3 4 5

輸出

1 2 4 5 3
在原排列中從後往前找,找到第乙個比它後面數小的數,既找到第乙個a[pos]滿足a[pos] < a[pos + 1],簡而言之就是找到原排列的最長單調遞減的字尾的前乙個樹。

在原排列的最長單調遞減的字尾中從前往後找到最後乙個大於a[pos]的數a[k]。

調換a[pos]和a[k]。

對a[pos+1]……a[n]進行轉置,此時的排列就是原排列的下乙個排列。

這裡舉個例子:如排列986375421,我們發現原排列的最長單調遞減的字尾是75421,而75421前面的第乙個數就是3,而這個數3也就是我們再找的a[pos]。之後在排列75421中從前往後找到最後乙個大於3的數,既是4,這裡我們可以用到二分查詢upper_bound函式找到第乙個小於3的數的位置,之後將位置減一就是k了。接著調換3和4,序列變為986475321,最後再將75321轉置成12357,則我們就求出了排列986375421的下乙個全排列為986412357。

還有,記得加乙個特判:如果說當前排列整體就是單調遞減的,那麼這也就是最後乙個排列了,直接跳出就ok了,既pos = 0時返回false。

# include # include # include # include using namespace std;

const int n_max = 10000;

int n, m;

int a[n_max + 10];

bool cmp(int x, int y)

bool permutation()

int main()

演算法 全排列問題 字典中介法

有時我們希望可以找到乙個全排列的下m個全排列,而不僅僅是下乙個,就這樣出現了字典中介法。洛谷1088 火星人 題目描述 求排列a 1 a 2 a 3 a n 之後的第m個全排列。輸入格式 共三行。第一行乙個正整數n 1 n 10000 第二行乙個正整數m 1 n 100 下一行是1到n這n個整數的乙...

全排列演算法之字典序法

字典序演算法如下 設p是1 n的乙個全排列 p p1p2.pn p1p2.pj 1pjpj 1.pk 1pkpk 1.pn 1 從排列的右端開始,找出第乙個比右邊數字小的數字的序號j j從左端開始計算 即 j max index return index 在pj的右邊的數字中,找出所有比pj大的數中...

全排列之字典序法

1 對於輸入的字典序排列,反向查詢第一對滿足a j 2 仍舊反向查詢第乙個下標k,使得 a j 3 交換a j 和a k 4 翻轉a j 1 a end 此法能適應有重複元素的系列 如下 include include using namespace std int cmp const void a...