【題目】
給出集合 [1,2,3,...,n]
,其所有元素共有 n!
種排列。
按大小順序列出所有排列情況,并一一標記,當 n = 3
時, 所有排列如下:
"123"
"132"
"213"
"231"
"312"
"321"
給定 n
和 k
,返回第 k
個排列。
示例 1:
輸入: n = 3, k = 3
輸出: "213"
示例 2:
輸入: n = 4, k = 9
輸出: "2314"
示例 3:
輸入: n = 3, k = 1
輸出: "123"
提示:
1 <= n <= 9
1 <= k <= n!
【題目解析】
解題方法
初始化:從1到n的數字列表,用于構建排列;一個記錄階乘的數組,用于快速計算不同長度下的排列數。
-
尋找第k個排列:
- 對于n個數,第一個數字的位置可以通過
(k-1)/(n-1)!
確定,其中(n-1)!
表示除第一個數字外,剩下的數字組成的排列總數。 - 確定第一個數字后,從列表中移除該數字,更新
k
值為k % (n-1)!
,繼續確定下一個數字。 - 重復上述過程直到所有數字確定。
- 對于n個數,第一個數字的位置可以通過
class Solution:
def getPermutation(self, n: int, k: int) -> str:
# 階乘數組,用于計算不同位置的索引
factorial = [1] * (n + 1)
for i in range(1, n + 1):
factorial[i] = factorial[i - 1] * I
# 因為k是從1開始計數的,我們將k轉換為從0開始
k -= 1
# 初始化數字列表和結果字符串
nums = [str(i) for i in range(1, n + 1)]
result = ''
# 從最高位開始確定每個位置的數字
for i in range(n, 0, -1):
# 確定當前位置的數字
index = k // factorial[i - 1]
k %= factorial[i - 1]
# 將確定的數字加到結果字符串,并從列表中移除
result += nums.pop(index)
return result
執行效率
image.png
【總結】
適用問題類型
- 需要從排列組合中直接定位到特定位置的排列。
- 排列數量龐大,無法直接枚舉所有排列的場景。
解決算法:基于階乘數系統的直接計算法
這種算法通過將排列問題轉換為階乘數系統的問題來解決,利用數學原理直接計算出第k個排列的具體形態。
算法特點
- 高效率:直接根據給定的序號k計算出排列,避免了生成全部排列的巨大開銷。
- 低空間消耗:除了最終的排列字符串,算法運行過程中僅需存儲階乘數值和當前可選數字,空間復雜度低。
- 易于實現:算法邏輯清晰,易于按照步驟實現。
時間復雜度與空間復雜度
-
時間復雜度:
O(n^2)
,主要時間開銷在于每次從列表中移除選定的數字,需要遍歷列表。 -
空間復雜度:
O(n)
,需要額外空間存儲階乘數值和當前可選數字列表。
實踐意義
這種算法為解決大規模排列問題提供了有效的工具,尤其是在需要高效處理大量數據、直接找到解而不是枚舉所有可能的情況時。在數據科學、密碼學等領域,找到快速解決組合數學問題的方法具有重要的應用價值。此外,學習和實現這種算法可以幫助提升對組合數學和算法設計的理解,增強解決復雜問題的能力。