全排列剖析 求n個數第k個排序 康托展開

2021-07-26 05:23:40 字數 1338 閱讀 2181

康托展開的公式:(不用記,看形勢就行,下面會有例子)

x=an*(n-1)!+an-1*(n-2)!+...+ai*(i-1)!+...+a2*1!+a1*0!

ai為整數,並且0<=ai適用範圍:沒有重複元素的全排列

第一類題:n個數的第k個排序,例子,1,2,3,4共有4!種排列,1234,1243,1324等等。按順序應該是

1234

1243

1324

1342

1423

1432等等

可以通過stl中next_permutation(begin, end);來算下乙個全排列,

理論上你要算n個數的第k個排列只要呼叫k-1次next_permutation()就行,但是一般來說肯定會超時的

,因為next_permutation的時間複雜度是o(n)(如果自己寫出來next_permutation時間複雜度比n大就要注意了,其中乙個容易疏忽的地方是最後排序可以用reverse而不是sort)。所以如果用這個的話時間複雜度是o(n^2)。

而用康托展開只要o(n)就行,下面來說說具體怎麼做:

題目:找出第16個n = 5的序列(12345)

首先第十六個也就是要前面有15個數,要呼叫15次next_permutation函式。

根據第一行的那個全排列公式,15 / 4! = 0 …15  =》  有0個數比他小的數是1,所以第一位是1

拿走剛才的餘數15,用15 / 3! = 2 …3   =>  剩下的數里有兩個數比他小的是4(1已經沒了),所以第二位是4

拿走餘數3, 用 3 / 2! = 1 …1   =》  剩下的數里有乙個數比他小的是3,所以第三位是3

拿走餘數1, 用 1/  1! = 1 …0    =>  剩下的數里有乙個數比他小的是 5(只剩2和5了),所以第四位是5

所以排列是 1,4,3,5,2

第二類題:已知是n = 5,求14352是它的第幾個序列?(同一道題)

用剛才的那道題的反向思維

第一位是1,有0個數小於1,即0* 4!

第二位是4,有2個數小於4,即2* 3!

第三位是3,有1個數小於3,即1* 2!

第四位是5,有1個數小於5,即1* 1!

第五位是2,不過不用算,因為肯定是0

所以14352是 n = 5的第 0 + 12 + 2 + 1 + 0 = 15    + 1(求的是第幾個,所以要加一) = 16

第16個,跟剛才那道題一樣,證明對了

**:

N個數,求第K大數

有n個不重複的數,這n個數可以放入記憶體中,讓你用最快的方法找到第k大的數。解答 一般情況我們可能考慮,先將n個數排序 快排序 堆排序 然後可以得到結果。但是當n很大時這樣做的效率會很低。所以我們提出一種更高效的方法 利用快速排序的特點 第一遍排序會確定乙個數的位置,這個數左邊都比它大,右邊都比他小...

N個數,求第K大數

今天同學給我出了一道題是這樣的 有n個不重複的數,這n個數可以放入記憶體中,讓你用最快的方法找到第k大的數。解答 一般情況我們可能考慮,先將n個數排序 快排序 堆排序 然後可以得到結果。但是當n很大時這樣做的效率會很低。所以我們提出一種更高效的方法 利用快速排序的特點 第一遍排序會確定乙個數的位置,...

LeetCode 第k個排列(康托展開)

給出集合 1,2,3,n 其所有元素共有 n 種排列。按大小順序列出所有排列情況,並一一標記,當 n 3 時,所有排列如下 123 132 213 231 312 321 給定 n 和 k,返回第 k 個排列。說明 給定 n 的範圍是 1,9 給定 k 的範圍是 1,n 示例 1 輸入 n 3,k ...