leetcode 60 第K个排列
1.题目描述
给出集合 [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”
2.解题方法
1.回溯法+减枝
思路分析:
采用DFS深度优先遍历,每层从小到达选择一个数字,利用
visited数组记录每个数字的访问情况 ,当递归深度超出数组长度
时,找到一种排列组合,序号+1,当前结果序号和目标序号k相同时,
找到结果,设置全局变量退出其他递归函数。
时间复杂度:O(n!)
空间复杂度:
ps:回溯法的时间复杂度过高,会导致超时错误。
2.逆康托法
思路分析:
采用递归的思路,在每一位上确定一个数字,每次确定数字后,
可形成(n-1)!种排列。
k从0开始,
确定第一位:
group = k / (n-1)!, 所以查询结果在组号为group的组中
k = k - group * (n-1)!,更新查询的序号.
例如:
[1,2,3,4], k = 15, n=4
group = up(15 / (3)!) = 3 , 第一位为nums[3-1] = 3,在第三组中
k = 15 % 3! = 3
确定第二位:
[1,2,4]
group = up(3 / (2)!) = 2 , 第二位为nums[2-1] = 2,在第二组中
k = 3 % 2 = 1
确定第三位:
[1,4]
group = up(1 / (1)!) = 1 , 第二位为nums[1-1] = 1,在第一组中
k = 1 - ((1 / (1)!)*(1!) = 0
确定第四位:
[4]
因为k=0,此时最后一位为nums[0]
1—> (n-1)!
2—> (n-1)!
3—> 1 —> (n-2)!
2 —> 2,1,4 —>(n-3)!
2,4,1
4 —> (n-2)!
4—> (n-1)!
3.代码
import math
class Solution:
def getPermutati