康托展開的公式:(不用記,看形勢就行,下面會有例子)
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 ...