网易20届提前批笔试第一题:字典序排列

其实这题就是在考字典序全排列,然后计算出总的排列数(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]。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值