給出集合 [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個排列,最簡單的方法就是利用遞迴或者非遞迴的形式生成所有的排列,然後選擇第k個,這樣的時間複雜度為o(n
!)
o(n!)
o(n!
),時間有點長,那麼,我們是否可以通過其他的方式直接獲取到第k個排列呢?答案是有的。
我們先通過逐個確認排列裡的每乙個數來得到最終的排列。
首先我們設排列為a1,
a2,⋯
,a
na_1,a_2,\cdots,a_n
a1,a2
,⋯,
an,我們來確認第乙個a
1a_1
a1。
根據排列的數量,我們可以很快的算出:
以1開始的排列有(n−
1)
!(n-1)!
(n−1)!
個,以2開始的排列有(n−
1)
!(n-1)!
(n−1)!
個,⋯
\cdots
⋯,以n開始的排列有(n−
1)
!(n-1)!
(n−1)!
個。所以我們可以推斷出當(i−
1)(n
−1)!
i(n− 1) !(i-1)(n-1)!(i −1)( n−1) !i(n− 1)!時,a1= ia_1=i a1= i。我們可以通過公式計算出a1= ⌊k−1 (n−1 )!⌋+ 1a_1=\lfloor\frac\rfloor+1 a1=⌊( n−1) !k−1 ⌋+1 ,在完成這一步以後,我們就可以繼續往下做了,此時待放入排列裡的數就變成[1, n]\a 1[1,n]\backslash a_1 [1,n]\ a1,k變成了k』,k′= (k−1 )mod (n−1 )!+1 k'=(k-1) mod(n-1)!+1 k′=(k− 1)mo d(n− 1)!+ 1。這樣就變成從n-1個數里選擇第k』個排列的子問題了,這樣就可以進行遞迴或者迴圈下去。時間複雜度為o(n 2) o(n^2) o(n2 )class
solution
--k;
string ans;
vector<
int>
valid
(n +1,
1);for
(int i =
1; i <= n;
++i)
} k %
= factorial[n - i];}
return ans;}}
;
第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 3,k ...