跳到主要内容

Permutation Sequence

描述

The set [1,2,3,…,n] contains a total of n! unique permutations.

By listing and labeling all of the permutations in order, We get the following sequence (ie, for n = 3):

"123"
"132"
"213"
"231"
"312"
"321"

Given n and k, return the kth permutation sequence.

Note: Given n will be between 1 and 9 inclusive.

分析

首先可以想到一个简单直白的方法,即调用 k-1next_permutation(),从而得到第k个排列。这个方法把前k个排列全部求出来了,比较浪费,时间复杂度是 O(kn),所以会超时。有没有办法直接求第k个排列呢?有!

利用康托编码的思路,假设有n个不重复的元素,第k个排列是a1,a2,a3,...,ana_1, a_2, a_3, ..., a_n,那么a1a_1是哪一个位置呢?

我们把a1a_1去掉,那么剩下的排列为 a2,a3,...,ana_2, a_3, ..., a_n, 共计n-1个元素,n-1个元素共有(n-1)!个排列,于是就可以知道 a1=k/(n1)!a_1 = k / (n-1)!

同理,a2,a3,...,ana_2, a_3, ..., a_n 的值推导如下:

k2=k%(n1)!k_2 = k\%(n-1)!

a2=k2/(n2)!a_2 = k_2/(n-2)!

\quad \cdots

kn1=kn2%2!k_{n-1} = k_{n-2}\%2!

an1=kn1/1!a_{n-1} = k_{n-1}/1!

an=0a_n = 0

康托编码

# Permutation Sequence
# 康托编码
# 时间复杂度O(n),空间复杂度O(1)
class Solution:
def getPermutation(self, n: int, k: int) -> str:
s = ''.join(str(i) for i in range(1, n + 1))
return self.kth_permutation(s, k)

def factorial(self, n: int) -> int:
result = 1
for i in range(1, n + 1):
result *= i
return result

# s 已排好序,是第一个排列
def kth_permutation(self, s: str, k: int) -> str:
n = len(s)
result = []
s = list(s)
base = self.factorial(n - 1)
k -= 1 # 康托编码从0开始

for i in range(n - 1, 0, -1):
idx = k // base
result.append(s.pop(idx))
k %= base
base //= i

result.append(s[0]) # 最后一个
return ''.join(result)

相关题目