給出集合 [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 = 3
輸出: 「213」
示例 2:
輸入: n = 4, k = 9
輸出: 「2314」
本題如果乙個乙個搜尋,直到找到第k個,會超時。所以用數學的方法:逆康托展開
康托展開是乙個全排列到乙個自然數的雙射,常用於構建雜湊表時的空間壓縮。 康托展開的實質是計算當前排列在所有由小到大全排列中的順序,因此是可逆的。
1.康托展開
給定乙個排列(b1
,b2,
...,
bn
)(b_1,b_2,...,b_n)
(b1,b
2,.
..,b
n),求它是第幾個排列,公式如下
x =a
n(n−
1)!+
an−1
(n−2
)!+.
..+a
10
!x=a_n(n-1)!+a_(n-2)!+...+a_10!
x=an(
n−1)
!+an
−1(
n−2)
!+..
.+a1
0!其中a
ia_i
ai是當前排列在bi+
1b_
bi+1到b
nb_n
bn中小於bib_
bi的元素個數。
例如(1,2,3,4,5)中的排列34152是第幾個排列:
a
5a_5
a5=2,因為4152中小於3的元素是1,2共兩個;
a
4a_4
a4=2,因為152中小於4的元素是1,2共兩個;
a
3a_3
a3=0,因為52中小於1的元素是0個;
a
2a_2
a2=1,因為2中小於5的元素是3共乙個;
a
1a_1
a1=0,因為2後已無元素。所以始終為0。
於是x =2
(5−1
)!+2
(5−2
)!+0
(5−3
)!+1
(5−4
)!+0
(5−5
)!
x=2(5-1)!+2(5-2)!+0(5-3)!+1(5-4)!+0(5-5)!
x=2(5−
1)!+
2(5−
2)!+
0(5−
3)!+
1(5−
4)!+
0(5−
5)!=61.
比34152小的組合有61個,所以34152是第62個排列。
2.逆康托展開
給定數(1,2,…,n),求第k個排列是什麼。類似於輾轉相除,每一次用k/(n-1)!,餘數為(1,2,…,n)中剩餘數字的位置,商為下一次的被除數。
例如a=(1,2,3,4,5)的第62個排列是什麼?先62-1=61,然後
61/(5-1)!=2…13,說明比首位小的數有2個,所以首位選a[2]=3,然後刪除a[2]=3得a=(1,2,4,5);
13/(4-1)!=2…1,說明比第二位小的數有2個,所以第二位選a[2]=4,然後刪除a[2]=4得a=(1,2,5);
1/(3-1)!=0…1,說明比第三位小的數有0個,所以第二位選a[0]=1,然後刪除a[0]=1得a=(2,5);
1/(2-1)!=1…0,說明比第四位小的數有1個,所以第二位選a[1]=5,然後刪除a[1]=5得a=(2);
0/(1-1)!=0…1,說明比第五位小的數有0個,所以第二位選a[0]=2,然後刪除a[0]=5得a=()。
所以最終得排列34152.
class
solution
}int temp_k=k-1;
while
(n!=0)
return res;}}
;
第k個排列
給出集合 1,2,3,n 其所有元素共有 n 種排列。按大小順序列出所有排列情況,並一一標記,當 n 3 時,所有排列如下 123 132 213 231 312 321 給定 n 和 k,返回第 k 個排列。說明 public string getpermutation int n,int k l...
第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 ...
第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...