LeetCode —— 60. 第k个排列(Python3)

给出集合 [1,2,3,…,n],其所有元素共有 n! 种排列。

按大小顺序列出所有排列情况,并一一标记,当 n = 3 时, 所有排列如下:

“123”
“132”
“213”
“231”
“312”
“321”

给定 n 和 k,返回第 k 个排列。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/permutation-sequence
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
————————————————————————————————
解题思路:最直接的方法就是使用深度优先遍历+回溯方法,但是这种方法应该会超时。这里选择用数学的办法进行分析:

假如给定集合[1,2,3,…,10],以1开头的的排列组合数为9!,以2开头的排列组合数为9!,。。。,以10开头的排列组合数为9!;回顾头来比较k和9!的大小关系,如果k小于9!,则第k个排列肯定以1开头,接着题目就变换为给出集合[2,3,4,…,10],求第k个排序,这样我们就得到了一个规模更加简单的问题,我们可以继续套用上面的解法进行求解。

如果 k > 9 ! k>9! k>9!,当 2 ∗ 9 ! > k > 9 ! 2*9!>k>9! 29!>k>9!的时候,表示第k个排列以2开头,接着令 k = k − 9 ! k=k-9! k=k9!,题目装换为给出集合[1,3,4,…,10],求第k个排序,这样我们同样得到一个规模更加简单的问题,继续套用相同的解法;、

其Python3代码如下:

class Solution:
    def getPermutation(self, n: int, k: int) -> str:
        strs = [str(i) for i in range(1,n+1)]  # 集合所有元素
        def sums(n):  # 阶乘函数
            if n == 1:
                return 1
            return n*sums(n-1)
        
        ans = ""  # 用于保存最终返回结果
        while k>0:  # 当k==0时证明找到第k个排列
            lens = len(strs)  # 用于进行阶乘,表示当前集合中剩下的元素个数
            if k==1:  # 当k=1时则表示当前集合的第一个排列,直接返回即可
                break
            for i in range(1,n+1):  # 遍历集合中的每一个元素
                k -= sums(lens-1)  # 减去以当前元素为起始位置的排列数量
                if k<=0:  # 当k小于零时,表示当前元素为最终目标的起始位置
                    ans += strs[i-1]  # 将其加入ans中
                    k += sums(lens-1)  # 回溯,使k加上阶乘
                    strs.pop(i-1)  # 删除集合中的当前元素
                    break  # 跳出for 循环
        ans += "".join(strs)  # 拼接strs中剩余的元素
        return ans

时间复杂度:最坏情况下,需要遍历整个集合才能找到合适的当前元素,因此时间消耗为 n + ( n − 1 ) + . . + 1 n+(n-1)+..+1 n+(n1)+..+1,所以时间复杂度为 O ( n 2 ) O(n^2) O(n2)
空间复杂度: O ( n ) O(n) O(n)

おすすめ

転載: blog.csdn.net/qq_37388085/article/details/108415219