題目
The set [1,2,3,…,n] contains a total of n! unique permutations.
By listing and labeling all of the permutations in order, we get the following sequence for n = 3:
“123”
“132”
“213”
“231”
“312”
“321”
Given n and k, return the kth permutation sequence.
Note:
Given n will be between 1 and 9 inclusive.
Given k will be between 1 and n! inclusive.
Example 1:
Input: n = 3, k = 3
Output: “213”
Example 2:
Input: n = 4, k = 9
Output: “2314”
題意
給出一個n說明一共有[1,2,…n]個可選數,然後按照字典序選出它排列組合的第k個
想法
這個當時學組合數學的時候有接觸過,最簡單的想法就是直接去周遊字典序然後當周遊到指定次數時停止,我沒有試過,因為我覺得這樣的方法還是蠻複雜,這裡的複雜是說處理複雜了,有很多備援,比如說你知道開頭為1的組合種類本來就比目标下标小,但你還是直接把1開頭的組合周遊了一遍,這個是沒有必要的。
我的想法就是能夠找出目前數字開頭的話能不能覆寫到目标數,比如n=4,k=9,以1開頭能覆寫到1x3!=6,不夠大,換2,2x3!=12,說明就在2的區間内,那你就把2之前的組合給做一個計數,然後遞歸去找,k=k-1x3!=3,這時候有個注意的地方就是2就在後面的序列中不能用了,這時候重新計數,1x2!=2,小了,2用過了,換3,2x2!=4,覆寫到了,繼續,k=k-1x2!=1,這時待選數字隻剩下[1,4],還是從小到大找,1x1!=1,剛好,k=k-0x1!=1,最後1x0!=1,完成覆寫。這裡有兩個地方需要注意,一個是選過的數字不能再選,另外一個是找到一個數剛好能覆寫到目标數後,目标數k減去的是這個數的前面的數能覆寫到的區域,因為目前數覆寫的區域是可能會大于目标數,我們的想法是遞歸縮小範圍。
參考代碼
class Solution:
def getPermutation(self, n, k):
"""
:type n: int
:type k: int
:rtype: str
"""
cnts = []
isused = []
result = []
for i in range(,):
cnts.append(cnts[i-]*i)
isused.append()
count =
idx =
i =
valid =
while idx<n:
if count+(valid+)*cnts[n-idx-]>=k:
result.append(i)
isused[i] =
count += valid*cnts[n-idx-]
idx = idx+
for j in range(,):
if isused[j]!=:
i = j
break
valid =
else:
for j in range(i+, ):
if isused[j]!=:
i = j
break
valid +=
return ''.join(str(i) for i in result)