Skip to main content

60. 第k个排列 [medium]

60. 第k个排列 [medium]

https://leetcode-cn.com/problems/permutation-sequence/

给出集合 [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"

通过次数41,069 | 提交次数83,887

Second Try

2020-07-29

按照阶乘排序的方式,一路迭代解决,直到可以选的元素都被选完。其实这个时候k=1,但是如果按照k=1来判断,则会在最后还剩一个元素没选择的时候提前终止。

这题需要注意的是rank的计算,容易出错;其次是需要列出所有可选的元素并按从低到高排序来进行选择。


class Solution:
def getPermutation(self, n: int, k: int) -> str:
# 直接按照阶乘递归排序来解决

rv = []
selections = list(range(1, n + 1))
while len(selections): # 用k来判断反而可能导致提前终止,有点麻烦
step = math.factorial(n - 1)
# k - 1是为了避免刚好在最后一位被整除;选择的位数从selections里选,idx从0开始,因此rank不用额外再+1.
rank = (k - 1) // step
rv.append(selections.pop(rank))
k = k - rank * step
n -= 1
# print("rv", rv, "k", k, "n", n)

return ''.join([str(i) for i in rv])
  • 执行用时:40 ms, 在所有 Python3 提交中击败了80.49%的用户
  • 内存消耗:13.7 MB, 在所有 Python3 提交中击败了7.69%的用户

First Try

2020-07-28

暴力解法, 只是优化了第一个数字的选择,后面的数字全靠暴力求解,排名果然在后5%。

但anyway,还是通过了。

注意点在于第一个数字的选择,还有其实rank的设置。由于层级是1 ~ n,而不是0 ~ n-1,同时还需要考虑k刚好在层级最后一个数的位置,因此所在的层级应该是 startx = (k - 1) // step + 1, 而不是startx = k // step.


class Solution:
def getPermutation(self, n: int, k: int) -> str:
# 全排列,直接定位根据k所在的第一个元素的位置,时间变为十分之一
step = math.factorial(n - 1)
# 1. k需要考虑到刚好为step大小的情况; 2. startx 可选为1 ~ n, 而非0 ~ n-1
startx = (k - 1) // step + 1
start_rank = (startx - 1) * step
# print("start x", startx, "start_rank", start_rank)
choices = [i for i in range(1, n + 1) if i != startx]
rank = {"val": start_rank}
def backtrack(choices, visited, seq):
# print('rank', rank, seq)
if len(visited) == len(choices):
rank["val"] += 1
if rank["val"] == k:
return True

for i in range(len(choices)):
if i in visited:
continue
visited.add(i)
seq.append(choices[i])
if backtrack(choices, visited, seq):
return True
seq.pop()
visited.remove(i)

return False

seq = [startx]
backtrack(choices, set(), seq)

return ''.join([str(i) for i in seq])

  • 执行用时:2764 ms, 在所有 Python3 提交中击败了5.03%的用户
  • 内存消耗:13.6 MB, 在所有 Python3 提交中击败了7.69%的用户