leetcode 第k个排列 python

60. 第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 = 3
输出: “213”
示例 2:
输入: n = 4, k = 9
输出: “2314”*

1. 暴力法
可以用递归全排列,将所有的可能都加入到一个列表中,进行排序,找到第K个就行了,这里就不做多述,因为时间复杂度太高了,肯定超时。
2.权值解法
有点像海明码的感觉,以n=6,k=100为例,我们来定义一下他们的权值,下面我们来看张图片
leetcode 第k个排列 python_第1张图片
当第六位确定之后,后面五位数最多能组成120个数(5!),也就是说图上6所在的位置,1代表120,2代表240,以此类推。我们定义图上6所在的位置的权值为120,当确定左边两位的时候,剩下四位最大可能组合为24种,我们定义其权值为24,剩下的就不一一说了,看上面的图。
下面我们来举个例子n=6,k=100;
首先n=6最大组合数是720,720>100说明6位数的组合数超过100,假定我们确定最高位为1
剩下的五位数最大组合数为120,120>100同理说明五位数的组合数超过100,同理我们可以判断四位数不行。大家都知道当确定位数后,最高位越小这个数越小,所以证明上面的假定成立,最高位为1。下面就不一一解说了,次高位权值为24,在剩下的数中【2,3,4,5,6】选取6(100/24=4点多,所以取第五位),确定两位后现在我们来确定第三高位,用剩下的(余数)4(100/24=4…..4)继续除以其权值6等于零点几,所以选剩下数列中第一位(2)。再继续用上次的余数4除以第四高位的权值2,等于2正好整除,选取剩下列表中的第二位【3,4,5】4,(正好整除的意思就是说在确定前面的高位的基础上,后面剩余得数选取他们的最大组合数就行了)所以,第五位第六位分别是5,3。最终我们可以得出第一百个数是(k=100)162453。自认说的不是很清楚,第一次写博客,如有疑问或建议欢迎回帖,谢谢。下面直接看代码。
这个代码的思路较清晰但是在LeetCode不能正常运行不知道是什么原因,我试过了window系统上的python2.X、python3.X和Linux终端都能正常运行。我猜测是取天花那一步出问题了,如果你们有兴趣可以加个if判断,我就懒得写了,之后我再复制一个我好早之前写的代码,有点不清晰,但是能通过用时LeetCode上用时28ms。

import math
class Solution(object):
    def getPermutation(self, n, k):
        """
        :type n: int
        :type k: int
        :rtype: str
        """
        templist=[]#定义一个列表,用于装放下面取出的数
        temp=[i for i in range(1,n+1)]#定义一个n位的列表1-n
        dicts={1:1,2:1,3:2,4:6,5:24,6:120,7:720,8:5040,9:40320,10:362880}#定义各位的权值
        for i in range(n,0,-1):
            s = math.ceil(k / dicts[i])#计算商值 取其天花
            templist.append(temp.pop(s - 1))#将对应数值,加入到templist中,并删除在temp中取出得数,避免重复取出
            if k%dicts[i]==0:#判断能整除
                templist.extend(temp[::-1])#将剩余数反转,即最大组合数
                break
            else:#如果不能整除,即将k值等于其余数
                k%=dicts[i]
        return ''.join([str(i) for i in templist])#将列表中数字先转化为str`

代码二

class Solution(object):
    def getPermutation(self, n, k):
        """
        :type n: int
        :type k: int
        :rtype: str
        """
        templist=[]
        temp=[i for i in range(1,n+1)]
        dicts={1:1,2:2,3:6,4:24,5:120,6:720,7:5040,8:40320,9:362880,10:3628800,11:39918600}
        for i in range(n-1,0,-1):
            if k<=dicts[i]:
                templist+=temp[:len(temp)-i]
                temp=temp[len(temp)-i:]
            else:
                if k==dicts[i+1]:
                    templist.append(temp[k//dicts[i]-1])
                    temp.pop(k//dicts[i]-1)
                    templist+=temp[::-1]
                    temp=[]
                    break
                else:
                    templist.append(temp[k // dicts[i]-1 if k%dicts[i]==0 else k // dicts[i] ])
                    temp.pop(k // dicts[i]-1 if k%dicts[i]==0 else k // dicts[i])
                    k = k % dicts[i]
                    if k==0:
                        templist += temp[::-1]
                        temp = []
                        break
        s1=''
        for s in templist+temp:
            s1+=str(s)
        return s1

你可能感兴趣的:(leetcode 第k个排列 python)