天天看點

Leetcode#60. Permutation Sequence

題目

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)