蓝桥杯 Python 组省赛夺奖班-5.2 排列组合

一、排列序数

题目

请添加图片描述
请添加图片描述

思路

itertools.permutations(iterable,r = None)
直接模拟即可

代码

from itertools import permutations
cnt = 0
s = input()
s_set = sorted(s)
for i in permutations(s_set):
    if "".join(i) == s:
        break
    cnt += 1
print(cnt)

二、拼数

题目

请添加图片描述

思路

坑巨多!要小心!
最初思路对字符串进行排序,但是忽略了组合的情况!
最终选择自己重写key函数,复杂度比老师的更低,具体的坑在代码注释里有

代码

## 错误示例1 忽略了第一位相同但是第二位不同
##n = int(input())
##a = list(input().split())
##a.sort(key = lambda x:x[0],reverse = True)
##print("".join(a))

## 错误示例2 忽略了自由组合时的情况
## 例如:4
##       7 6 75 1
## 结果为75761 但是正确结果为 77561
##n = int(input())
##a = list(input().split())
##a.sort(reverse = True)
##print("".join(a))

## 老师的正确代码,采用选择排序,复杂度o(n^2)
##n = int(input())
##nums = input().split()
##for i in range(0,n-1):
##    for j in range(i+1,n):
##        if nums[j]+nums[i] > nums[i]+nums[j]:
##            nums[i],nums[j] = nums[j],nums[i]
##print("".join(nums))

## 重写key,复杂度为o(nlogn),python内部sort()使用Tim-sort
from functools import cmp_to_key
n = int(input())
a = input().split()
def mycmp(x,y):
    if x+y > y+x:
        return 1
    else:
        return -1
a.sort(key = cmp_to_key(mycmp),reverse = True)
print("".join(a))

三、火星人

题目

请添加图片描述
请添加图片描述

思路

老师讲的真好,我是真的想不到这样搞,唉太笨了
从后往前找,一旦有后一位比前一位大说明前面这一位可以换成一个更大的数,假设找到要更换的位置为k,那么应该选k+1到最后所有数中满足大于第k个数的最小数交换,然后从k+1处进行颠倒,这里注意其实从k+1到最后都已经是降序了!可以利用这个性质!
还有注意不要直接读入字符串!因为火星人的手指有成千上万根!
并且"11" < “2” 但是 11 > 2 !!!

代码

n = int(input())
step = int(input())
## 这里巨坑!!! 不能直接使用a = input().split() 因为火星人手指有成千上万根!
## "11" < "2" 但是 11 > 2 !!!
## 焯!成千上万根手指 ●◡● 
a = list(map(int,input().split()))
def mynext(b):
    for i in range(n-1,0,-1):
        if b[i] > b[i-1]:
            for j in range(n-1,i-1,-1):
                if b[j] > b[i-1]:
                    b[i-1],b[j] = b[j],b[i-1]
                    return b[:i]+b[n-1:i-1:-1]
            
for i in range(step):
    a = mynext(a)
print(" ".join([str(i) for i in a]))
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值