蓝桥杯练习题——完美的代价(python题解)全部通过

问题分析:

关键是要找到贪心策略。对于这一题来说,首先判断这个字符串能不能够经过交换变成完美的回文字符串,满足条件后每一步都使用贪心策略。

①判断:
若字符串长度为偶数,则每个字符出现的次数都必须是偶数次,否则不对称
若字符串长度为奇数,则只能有一个字符出现奇数次(在字符串最中间出现一次)
判断实现比较简单,注意减少代码复杂度(题给字符串长度范围是8000,python很容易运行超时)
②贪心策略:
对于偶数长度的字符串,我们从第一个开始遍历,再倒序遍历出同样的,这个倒序遍历出来的序号,就是该移动的步数。 倒序列表需要不断更新,已经构成回文的外层字符不再考虑。
对于奇数的字符串,其实贪心策略和偶数的时候一样,只不过我们一直遍历下去会有一个字符没有匹配,那么这个字符肯定是放在中间的,我们设置一个判断,假如剩余的该字符个数不是1,按照和偶数一样的遍历,如果该字符是1,直接移动到最中间的位置。

图解:
在这里插入图片描述
省时策略:

python中的迭代和交换都要花费大量的时间。

在改进的代码中,对于找到的字符,我不对它进行逐次的交换,而是直接pop掉,利用它的索引找到需要移动的次数。

下一次的遍历针对的即是已经去掉外层字符的新列表,这样迭代下去,列表会越来越短,就达到了省时的目的。

详细代码:

n = int(input())
pal = list(input())

count = 0 #count用来计交换的次数
flag = 0  #flag判断是否已经有一个单独的奇个数的字符了
i=0 #用于计数外层丢弃的字符(单侧)

while(len(pal)>1):
    for k in range(len(pal)-1,0,-1):  # 从后面往前一直到1,寻找和pal[0]相同的pal[k]
        if pal[k] == pal[0]:
            #print(k)
            count += len(pal) - k - 1  # 计数器加 len(pal)-k-1
            #print(count)
            #最外层的已构成回文,不考虑了
            pal.pop(0)#注:pal(i)被pop掉后,索引整体前移1,所以k的位置需要-1
            i+=1
            pal.pop(k-1)#把找到的字符直接移到最外层,即直接pop掉
            break

        elif k == 1:  # 如果找不到相同的,该字符放到中间
            pal.pop(0)  #找不到的这个数丢弃,不能影响后续判断
            # impossible的两种情况:
            # ①偶数个字符,却存在一个字符出现奇数次
            # ②奇数个字符,但已经有一个字符只出现奇数次了,不能再出现下一个
            if n % 2 == 0 or flag == 1:
                print('Impossible')
                exit()
            flag = 1
            count += int(n/2) - i #把出现奇数次的字符直接移到中间需要的步数
print(count)
  • 25
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 12
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值