给出集合 [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:回溯法,跟46题一样,不过超时了,代码还是贴上吧。
class Solution(object):
def getPermutation(self, n, k):
nums = list(range(1,n+1))
res = []
def backtrack(nums ,tmp):
if not nums:
res.append(tmp)
return
for i in range(len(nums)):
backtrack(nums[:i] + nums[ i +1:], tmp + [str(nums[i])])
backtrack(nums ,[])
return ''.join(res[k-1])
思路2:从一个[1,n]的区间内挑数字(也就是代码中的nums)加入答案(直到全挑光),按什么顺序挑哪个数字呢?我们需要通过数学判断。
挑选过程如下:
比如n=4,证明一共有4!种排序,那我们当前的第k个排序是什么呢?我们先确定这个排序的第一个数字。我们知道对于每个数字开头的序列,在它确定的情况下,一共有(n-1)!种情况。比如1开头的n=4的序列,一共有3!种情况。那我们就可以通过k//(n-1)!来确定这是以哪个数字开头的序列,如果等于0, 那就是1,如果等于1那就是2,以此类推。
具体来说是:
- n 个数字有 n!种全排列,每种数字开头的全排列有 (n - 1)!种。
- 所以用 k / (n - 1)! 就可以得到第 k 个全排列是以第几个数字开头的。
- 用 k % (n - 1)! 就可以得到第 k 个全排列是某个数字开头的全排列中的第几个。
比如:
"123"
"132"
"213"
"231"
"312"
"321"
n=3,k=3
先确定开头的数字: k / (n - 1)! = 3/(3-1)!=1,那么第一个数字就是nums=[1,2,3]的索引为1的值,为2。
然后得到2+{1,3}全排列, k % (n - 1)! = 1 ,那么指的是以2个数字开头的全排列{1,3}中的第1个,{1,3}全排列为(1,3)和(3,1),所以为(1,3),结果为213。
https://blog.csdn.net/weixin_41958153/article/details/81234523
代码实现1:
class Solution:
def getPermutation(self, n, k):
self.fac = [1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880]
# 找到对应的n应该对应的fac坐标,就是在第一项确定的情况一下,有(n-1)!种组合
i = n - 1
# 构建序列,这个num是用来储存我们当前可以添加的数的,也是为避免重复
num = list(range(1, n + 1))
ret = ""
while i >= 0:
# a用来获得我们要求的那一位在num里的下标
a, b = k // self.fac[i], k % self.fac[i]
# 如果刚好整除干净,证明还在上一层
if b == 0:
a -= 1
if a >= 0:
ret += str(num[a])
del num[a]
i -= 1
k = b
# 如果刚好整除完,则我们已经可以知道接下来的排序情况了,它一定是最大的
# 所以把剩下的可选的数字reverse来制造这种效果
if b == 0:
for i in reversed(num):
ret += str(i)
break
return ret
s = Solution()
res = s.getPermutation(n=3,k=3)
print(res)
代码实现2:
class Solution:
def getPermutation(self, n, k):
series = [str(i + 1) for i in range(n)]
res = ''
cr = self.factorial(n)
while n:
cr //= n
n -= 1
temp = (k - 1) // cr
res += series.pop(temp)
k -= cr * temp
return res
def factorial(self, n):
if n < 2:
return 1
res = 1
for i in range(1, n + 1):
res *= i
return res