给出集合 [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个排列:
def npl(n,m,ans): #n是n个数字的列表
if len(m)==len(n):#达到长度,加入全排列列表ans
ans.append(m)
else:
for i in n:
if i not in m: #加入不重复的数字
npl(n,m+[i],ans) #递归
pl=[]
for i in range(1,n+1):
pl.append(i)
ans=[]
npl(pl,[],ans)
ans.sort() #先按从小到大是顺序排序
A=ans[k-1]
c=''
for i in A: #返回是字符串
c=c+str(i)
return c
[9 199269]妥妥超时了
加一条回溯条件:
def npl(n,m,ans,k):
if len(ans)==k:
return
依旧超时,但是正确,表明递归的答案是按顺序返回的。所以程序不用加ans.sort()
第二次代码:用数学方法确定每次选择的数字,例如k=10,n=4,l=[1,2,3,4],10/3!=1,10%3!=4,所以取l[1]=2,第一个数字是2,更新k=10%3!=4,第二轮循环,l=[1,3,4],4/2!=2,4%2!=0,因此第二个数取l[2-1]=3,k=0,第三轮循环,l=[1,4], 0/1!=0,0%1!=0,第三个数取l[0]=1,同理,第四个数取4
python竟然没有计算阶乘的代码,只能自己写递归了。
因为返回一个字符串,所以这次不采用递归,使用while循环:
def jc(n):
if n==1 or n==0:
return 1
else:
return n*jc(n-1)
l=[]
ans=''
for i in range(1,n+1):#n=4,l=['1','2','3','4']
l.append(str(i)) #方便返回字符串
while l :
n1=len(l)-1#计算当前l中每个数字可以有多少种排列
#如l=[1,2,3],以1,2,3开头的数分别有两种排列
n2=jc(n1) #数学描述就是阶乘
n3=k%n2 #计算余数,即下一轮的 k,
n4=k/n2 #用来选择当前循环选择的数字
if n3==0: #判断是否处于某个数排列的最后一个
n4=n4-1 #例[1,2,3],1有两种排列,k=2时,还是选择1开头
#所以n4要减1
if k==1 : #若是第一个排列,直接返回列表值,可去,单纯为了加速
for j in l:
ans=ans+j
return ans
else: #若是其他情况,取列表第n4个元素到ans,继续循环
ans=ans+l[n4]
k=n3
l.pop(n4) #取过的元素删除
return ans
32ms,排名24.5%