蓝桥杯:排列距离

题目:

小蓝最近迷上了全排列, 现在他有一个长度为 17 的排列, 里面包含的元素 有: abcdefghijklnopqr, 即 a 至 rr 中除了 mm 以外的所有小写字母, 这 17 个字母在任何一个排列中都恰好出现一次。前面几个排列依次是:

第 1 个排列为: abcdefghijklnopqr;

第 2 个排列为: abcdefghijklnoprq;

第 3 个排列为: abcdefghijklnoqpr;

第 4 个排列为: abcdefghijklnogrp;

第 5 个排列为: abcdefghijklnorpq;

第 6 个排列为: abcdefghijklnorqp;

第 7 个排列为: abcdefghijklnpoqr;

第 8 个排列为: abcdefghijklnporq;

第 9 个排列为: abcdefghijklnpqor;

第 10 个排列为: abcdefghijklnpqro。

对于一个排列, 有两种转移操作:

  1. 转移到其下一个排列。如果当前排列已经是最后一个排列, 那么下一个 排列就是第一个排列。

  2. 转移到其上一个排列。如果当前排列是第一个排列, 那么上一个排列就 是最后一个排列。

小蓝现在有两个排列, 分别为排列 A:A: aejcldbhpiogfqnkr, 以及排列 BB : ncfjboqiealhkrpgd, 他现在想知道, 在只有上述两种转移操作的前提 下, 排列 AA 最少转移多少次能得到排列 BB 。

答案提交

这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一 个整数, 在提交答案时只填写这个整数, 填写多余的内容将无法得分。

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 512M

难点:

自己走了一遍包括看了并理解了题解,其实难点就是长度为17的字符串一共有多少总排列,和如何确定这个排列是第几个排列

题解中很好的解决了这个问题,但没有过多的解释,下面是一些关于我的理解和注释后的代码,应该好好思考之后是可以理解的。

代码(python):

import os
import sys

# 请在此输入您的代码
# mp用于存储第一个排列中每一个字母对应的位置,用字典的方式
mp = {}
s1 = "aejcldbhpiogfqnkr"
s2 = "ncfjboqiealhkrpgd"
arr = [0]*20
arr[0] = 1 
# 初始化arr,arr[i]用于存储长度为i字符串最多有多少种排列,算是一个规律
for i in range(1,18):
  arr[i] = arr[i-1]*i

# 获取s这个字符串是第几个排列
def work(s):
  ans = 0
  n = len(s)
  for i in range(n):
    # 获取这个字母的位置,赋值给val
    val = mp[s[i]]
    # 哇趣,很聪明的方法计算第几个排列,一个字母一个字母来看
    # 找到这个字母往前移的位置,字母后面则表示已经进行了几次全排列
    # 如果在原本位置上的话,即与第一个排列一样,则val会减到0,既不用加上ans
    for j in range(i):
      if s[j] < s[i]:
        val-=1
    ans = ans + val * arr[n-1-i]
  return ans

# 因为缺少字母m,所以不能直接用码来获取位置,初始化mp字典
cnt = 1
for ch in "abcdefghijklnopqr":
  mp[ch] = cnt
  cnt+=1

a1 = work(s1)
a2 = work(s2)
# 正过来和反过来中较小的那一个
ans = min(a2-a1, arr[17]-a2+a1)
print(ans)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值