给出集合 [1,2,3,…,n]
,其所有元素共有 n! 种排列。
按大小顺序列出所有排列情况,并一一标记,当 n = 3 时, 所有排列如下:
"123"
"132"
"213"
"231"
"312"
"321"
给定 n 和 k,返回第 k 个排列。
说明:
示例 1:
输入: n = 3, k = 3
输出: "213"
示例 2:
输入: n = 4, k = 9
输出: "2314"
解题思路
首先想到的最简单的做法就是将所有的排列情况列出来,然后挑选出第k-1
个即可。这里有一个trick
,我们可以不将所有的情况列出,而是通过生成器遍历
class Solution:
def getPermutation(self, n, k):
"""
:type n: int
:type k: int
:rtype: str
"""
for i, per_list in enumerate(itertools.permutations([i + 1 for i in range(n)])):
if i == k - 1:
return ''.join([str(i) for i in per_list])
如果像下面这样写的话就会超时。
class Solution:
def getPermutation(self, n, k):
"""
:type n: int
:type k: int
:rtype: str
"""
per_list = list(itertools.permutations([i + 1 for i in range(n)]))
return ''.join([str(i) for i in per_list[k-1]])
但是这种写法显然很烂,我们可以通过递归的方法解决这个问题。对于n=4
时,我们实际上会产生如下四种情况:
我们知道对于每种情况都会有(n-1)!
种子集,对于上列来说就是6
种子集。如果k=14
的话,我们知道它一定在 3 + p e r m u t a t i o n ( 2 , 1 , 4 ) 3+permutation(2,1,4) 3+permutation(2,1,4)中,并且是 p e r m u t a t i o n ( 2 , 1 , 4 ) permutation(2,1,4) permutation(2,1,4)的第二个子集(14-12=2,我们是按照例子中的index
考虑,也就是数列从1
开始。如果按照从0
开始的话,我们输入就要变成14-1=13
)。我们看 p e r m u t a t i o n ( 2 , 1 , 4 ) permutation(2,1,4) permutation(2,1,4)可以分为如下三种情况
我们知道对于每种情况都会有(n-2)!
种子集,对于上列来说就是2
种子集。我们知道它一定是在 1 + p e r m u t a t i o n ( 2 , 4 ) 1+permutation(2,4) 1+permutation(2,4)中,并且是 p e r m u t a t i o n ( 2 , 4 ) permutation(2,4) permutation(2,4)的第二个子集,也就是(4,2)
,所以最后的结果就是"3142"
。我们可以非常轻松的得到如下递推公式
边界问题也非常容易,我们只要考虑n==1
时,返回n_list[0]
即可。
class Solution:
def getPermutation(self, n, k):
"""
:type n: int
:type k: int
:rtype: str
"""
factorials = [1]*(n+1)
for i in range(1, n+1):
factorials[i] = factorials[i-1]*i
n_list = [i for i in range(1, n+1)]
return self.helper(n, k-1, n_list, factorials)
def helper(self, n, k, n_list, factorials):
if n == 1:
return str(n_list[0])
m = k // factorials[n-1]
k %= factorials[n-1]
res = str(n_list[m])
n_list.remove(n_list[m])
res += self.helper(n-1, k, n_list, factorials)
return res
这个问题通过迭代也可以非常快的实现。
class Solution:
def getPermutation(self, n, k):
"""
:type n: int
:type k: int
:rtype: str
"""
factorials = [1]*(n+1)
for i in range(1, n+1):
factorials[i] = factorials[i-1]*i
n_list = [i for i in range(1, n+1)]
k -= 1
res = ''
for i in range(1, n+1):
m = k // factorials[n-i]
k %= factorials[n-i]
res += str(n_list[m])
n_list.remove(n_list[m])
return res
reference:
https://leetcode.com/problems/permutation-sequence/discuss/22507/“Explain-like-I’m-five”-Java-Solution-in-O(n)
我将该问题的其他语言版本添加到了我的GitHub Leetcode
如有问题,希望大家指出!!!