Leetcode 60. Permutation Sequence 第k个排列
标签: Leetcode
题目地址:https://leetcode-cn.com/problems/permutation-sequence/comments/82926
题目描述
给出集合 [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"
算法描述
最初我也想着利用之前的全排列先进行排列,拿到结果后对第k
个进行输出,但是很遗憾超时,所以后来看了别人的方法,发现了一种很巧妙的方法。其实类似于我们内存的寻址。比如当前的数组是[1,2,3,4]
,我们要计算第k个,我们发现这个数组有如下规律:
1+prem([2,3,4])
2+prem([1,3,4])
3+prem([1,2,4])
4+perm([1,2,3])
而我们有知道对应每一个perm
来说有n!
个结果,所以如果我们要第k
个,我们可以很清楚知道他在第k/(n-1)!
块,在块内的第k%(n-1)!
个,而对于快内的第几个,我们同样可以按照上面的方法做下去。知道得到最终结果。
其实理解起来也很容易,但是参考别人代码的时候,有一个地方不是很明白,在循环之前都进行了k-1
,后来经过推算知道了,因为k是个数,是从1开始的,而块(数组索引)是从0开始的,所以k先减去1做统一。比如我们从[1,2]
里面取第k=1
个,如果k不减1,那么先进行k/(2-1)! = 1,k%(2-1) = 1
,则结果不正确。
python代码
class Solution(object):
def getPermutation(self, n, k):
"""
:type n: int
:type k: int
:rtype: str
"""
nums = [str(i) for i in range(1,n+1)]
if k==1:
return "".join(nums)
fact = 1
for i in range(1,n):
fact *=i # (n-1) !
round = n - 1 # 轮数
# k 是从1开始,而索引从0开始,所以k-=1
# 比如 [1,2] 我们如果k = 1的话, 则k//1 = 1 k%1 = 1,可以发现将会以2开头,所以出错
k -= 1
finalRes = []
while round >= 0:
index = int(k / fact)
k %= fact
finalRes.append(nums[index])
nums.remove(nums[index])
if round > 0:
fact /= round
round -= 1
return "".join(finalRes)
参考: