其实这题就是在考字典序全排列,然后计算出总的排列数(n的阶乘),倒数第Q个排列即为正数(n!-Q+1)个排列,但是注意在python中的index是从0开始的。
所以当找到给定排列的位置idx后,倒数第Q个排列的位置是:(n!-(idx+1)+1)-1 = n!-idx-1
考试的时候傻了,用一个list去储存所有的排列,其实根本不需要的。
真的傻了傻了。
def permute(nums, n, total):
cnt = 0
idx = 0
while True:
try:
if nums == myinput:
idx = cnt
low_index = n-1
while low_index > 0 and nums[low_index-1] > nums[low_index]:
low_index -= 1
if low_index == 0:
break
low_index -= 1
high_index = low_index + 1
while high_index < n and nums[high_index] > nums[low_index]:
high_index += 1
high_index -= 1
nums[low_index], nums[high_index] = nums[high_index], nums[low_index]
nums[low_index+1:] = reversed(nums[low_index+1:])
cnt += 1
if cnt == total - idx - 1:
return nums
except:
break
if __name__ == '__main__':
n = int(input())
myinput = list(map(int, input().split()))
# res_list = func(n, myinput)
total = 1
for i in range(1, n + 1):
total = total * i
nums = list(range(1, n + 1))
nums.sort()
res_list = permute(nums, n, total)
for i in range(len(res_list)):
res_list[i] = str(res_list[i])
print(' '.join(res_list))
其实下面这种方法也可以实现字典序排序:
class Solution:
def permute(self, n, nums, myinput):
nums = list(range(1, n+1))
nums.sort()
path, res = [], []
flag = [False for _ in range(n)]
mylist = self.func(nums, 0, n, path, res, flag)
for i in range(len(mylist)):
if mylist[i] == myinput:
return mylist[len(mylist)-i]
def func(self, nums, idx, size, path, res, flag):
if idx == size:
res.append(path[:])
for i in range(size):
if not flag[i]:
path.append(nums[i])
flag[i] = True
self.func(nums, idx+1, size, path, res, flag)
path.pop()
flag[i] = False
return res
然而,在牛客网上和大家讨论了之后发现,其实从数学上还有非常简单的做法,即:
1.实际上按照字典序排列,这个字典序是对称的,正序里的最大值,对应倒序里最小值的位置,第二最大和第二最小也是对称的,同理,按照大小来说都是对称;所以正序的第Q个序列,与倒数的第Q个序列,对称,假设正序第Q个是a,a+2,a+1;那么倒序的第Q个应该是a+2,a,a+1;
2.所以,如果所给序列为L=[x1,x2,x3,…,xn],输出序列应该为[max(L)+min(L)-x1,max(L)+min(L)-x2,…,max(L)+min(L)-xn]。