60第K个排列
题目:给出集合 [1,2,3,…,n],其所有元素共有 n! 种排列。按大小顺序列出所有排列情况,并一一标记,当 n = 3 时, 所有排列如下:
"123"
"132"
"213"
"231"
"312"
"321"
给定 n 和 k,返回第 k 个排列。
说明:给定 n 的范围是 [1, 9]。给定 k 的范围是[1, n!]。
来源: https://leetcode-cn.com/problems/permutation-sequence/
法一:自己的代码 耗时很短,利用python自带的阶乘函数计算耗时会更短
思路:转化为一个纯数学的问题,关键是要把每种情况都考虑到,特别是除n!后是整数的情况,举例的时候就要把每种情况都枚举到,编程才不会出错
import math class Solution: def getPermutation(self, n: int, k: int): # 自定义阶乘函数 def n_factorial(x): if x == 0: return 1 else: return x * n_factorial(x-1) nums = [i+1 for i in range(n)] result = '' while n > 0: n = n - 1 # 通过观察数据可以看出,假如输入是(4,9),则说明以1开头的有3!个,以2开头的有3!个, # 所以用9除以3的阶乘是1.5,1,5向上取整为2,即nums中的第二个数2是结果中的第一个数, # 再用9减去6为3表示从2开始的组别中找第三个数, res = k / n_factorial(n) res_up = math.ceil(res) # 注意这里向下取整必须是向上取整后减1,这是因为比如输入的是(4,6),则6除3!为1,1-1=0,所以不可直接向下取整 res_down = res_up - 1 k = k - res_down * n_factorial(n) result = result + str(nums[res_up-1]) del nums[res_up-1] print('-'* 20) print('k', k) # print(res) print(res_up) # print(res_down) return result if __name__ == "__main__": duixiang = Solution() a = duixiang.getPermutation(4,9) print(a)
法二:自己的代码 利用回溯,但是超时,超时是因为没有用continue,每个分支都要检查一遍
class Solution: def getPermutation(self, n: int, k: int): nums = [i+1 for i in range(n)] global count,result count = 0 def backtrack(a='', nums=nums, ): global count,result # print('k',count) if count == k: return if len(a) == n: count += 1 # print('count', count) if count == k: result = a # exit() # return count for i,j in enumerate(nums): r = nums.copy() del r[i] # print('ttt',count) # sign,result = backtrack(a+str(j), r) backtrack(a+str(j), r) backtrack() return result
改进后的不会超时,注意这里return的用法,非常巧妙
class Solution: def getPermutation(self, n: int, k: int): nums = [i+1 for i in range(n)] from1to9_factorial = [1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880] def backtrack(a='', nums=nums,k = k ): # 一旦满足条件立即逐层返回a,结束所有函数 if len(a) == n: return a t = from1to9_factorial[len(nums) - 1] for i,j in enumerate(nums): if k > t: # 执行剪枝操作,如果大于t了,就结束本次循环 k = k - t continue # r中是下次for循环要遍历的数 r = nums.copy() del r[i] # 这里必须用return,避免了定义全局变量来解决问题 return backtrack(a+str(j), r, k) return backtrack() if __name__ == "__main__": duixiang = Solution() a = duixiang.getPermutation(4,10) print(a)