力扣 060 第k個排列

2021-10-09 07:32:32 字數 1873 閱讀 4457

給出集合 [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 ...