编程经典题-报文重排序
文章目录
前言
最近笔者碰到一些有趣的编程题目,题意既贴近日常生活又引人思考,很适合大家做练手,增强编程思维。下面分享出具体题目和几种解题方法。
题目:报文重排序
对报文进行重传和重排序是常用的可靠机制,重传缓存区内有一定数量的子报文,每个子报文在原始报文中的顺序已知,现在需要恢复出原始报文。
- 输入描述
输入第一行为N,表示子报文的个数,0<N<1000。
输入第二行为N个子报文,以空格分开,子报文格式为字符串报文内容+后缀顺序索引,子报文内容由[a-z,A-Z]组成,后缀为整型值,表示顺序,顺序唯一。
- 输出描述
输出恢复出的原始报文。按照每个子报文的顺序的升序排序恢复出原始报文,顺序后缀需要从恢复出的报文中删除掉
输入:
4
roling3 stone4 like1 a2
输出:
like a rolling stone
一、问题分析
在计算前首先让我们来做一个题目分析。有两个输入行参数,分别代表子报文个数和子报文,表示要有两个变量做接收。“子报文格式为字符串报文内容+后缀顺序索引,后缀为整型值,表示顺序,顺序唯一。”描述的是报文的数据结构,后缀是唯一的表示我们可以从这里下手,对后缀索引进行排序,排序后删除后缀,从而得到正确的报文顺序。
二、解题方法
1.方法一 匹配法(只能接收10以内参数)
代码如下(示例):python语言
# -------------参数接收区------------
num = int(input())
str = input()
#将接收到的字符串切分
split_str = str.split(' ')
# -------------变量定义区------------
dict = {} # 中间结果
list1 = [] # 接收结果
# -------------计算区------------
for i in split_str:
dict[i[-1]] = i[0:len(i) - 1]
for i in range(1, num + 1):
for j in dict.keys():
if i == int(j):
list1.append(dict[j])
# -------------结果输出区------------
for i in list1:
print(i,end=' ')
上面代码,首先按照编程规范划分多个分区,目的是提高代码可读性,通俗易懂代码逻辑,建议大家平时也要多写注释,养成良好的编程习惯。
程序开始接收两个参数分别是报文个数和子报文,由于传入的子报文是一个字符串所以我们要先做切割。接着定义两个容器用来接收计算时产生的中间结果和最终结果。
在计算区我们遍历所有切开后的子报文,由于报文后缀就是序号我们将后缀提取出来作为键,将字符串报文作为值,用字典保存起来,方便我们查询。由于报文的数量一定不会超过接收的报文个数参数,所以我们遍历报文个数,匹配字段中的key,并将字典的值保存在列表中。遍历列表中的所有元素就是我们要得到的最终结果。
这里注意,上面的代码虽然能运行通过部分案例,但是实则是有缺陷的!因为在计算时,我们用分片直接取字符串最后元素的方式,如果后缀序号超过9我们是截不到的。这里建议大家在做题的时候一定要考虑周全,程序完成后要经过大量的测试用例进行测试。
2.匹配法(升级版)(不受参数限制)
# 整理报文
# -------------参数接收区------------
num = int(input())
str = input()
str_res=''
res = str.split(' ')
# -------------变量定义区------------
dist = {}
# -------------计算区------------
for i in res:
for j in i:
if ord(j) not in range(65, 123): # 不在范围内
# print(j,end='')
str_res=str_res+j
dist[str_res]=i[0:len(i)-len(str_res)]
str_res=''
# -------------结果输出区------------
for i in range(1, num + 1):
for j in dist.keys():
if i == int(j):
print(dist[j],end=' ')
方法一的漏洞引出了方案二,在计算区我们抛弃了切片的方式,用ASCII码值来区分报文字符串和序号,不在数字范围内的(65, 123)即是报文。
方法三 使用第三方包
还在自己写算法?告诉你,站在巨人的肩膀上,事半功倍!这里直接调用三方包sort(),节省大量代码。
# 整理报文
# -------------参数接收区------------
num = int(input())
str = input()
str_res = ''
res = str.split(' ')
# -------------变量定义区------------
list1 = []
dist = {}
# -------------计算区------------
for i in res: # todo i: i1,love2,you3,too41
for j in i: # todo j: i,1,l,o,v,e,2,y,o,u,3,t,o,o,4,1
if ord(j) not in range(65, 123): # todo ascii码 不在 range(65, 123)
# print(j,end='')
str_res = str_res + j
dist[str_res] = i[0:len(i) - len(str_res)]
str_res = ''
# -------------结果输出区------------
for i in dist.keys():
list1.append(i)
list1.sort() # 排序
# 输出
for i in list1:
print(dist[i],end=' ')
方法四 算法
别人的用不惯?喜欢自研、琢磨?我们自己写算法!
# 整理报文
# -------------参数接收区------------
num = int(input())
str = input()
str_res = ''
res = str.split(' ')
# -------------变量定义区------------
list1 = []
list_res = []
dist = {}
# -------------计算区------------
for i in res: # todo i: i1,love2,you3,too41
for j in i: # todo j: i,1,l,o,v,e,2,y,o,u,3,t,o,o,4,1
if ord(j) not in range(65, 123): # todo ascii码 不在 range(65, 123)
# print(j,end='')
str_res = str_res + j
dist[str_res] = i[0:len(i) - len(str_res)]
str_res = ''
# todo ******************算法方式*******************
for i in dist.keys(): # 排序
list1.append(i)
i = 0
len1=len(list1)
while i < len1:
print('列表长度:',len(list1))
print('i:',i)
min = list1[0] # 初始化min值(min值已经拿走了)
j = 0 # 初始化j值(j值经过多次循环,已经变化,要重置)
print('j:', j)
while j < len(list1):
if min < list1[j]:
pass
else:
min = list1[j]
j = j + 1
list1.remove(min)
list_res.append(min)
print(list_res)
i = i + 1
for i in list_res:
print(dist[i],end=' ')
相比上一种方法,自己写算法还是挺费头发的~
方法五 正则表达式
# 整理报文
import re
# 接收输入
num = int(input())
str = input()
str_res = ''
# todo 中间结果
dict1={}
# todo提取键(正则表达式法)
list_key=re.findall('\\d+', str) #为啥起名这么长?因为长才知道它是列表!不是key!
list_value=re.findall('[a-zA-Z]+', str)
# 列表索引
for i in range(0,num):
dict1[key[int(i)]]=value[i]
# 字典索引
for i in range(1, num+1):
print(dict1[str(i)],end=' ') #为什么用str()再转一下?
#因为虽然range生成的是int类型,但是它只是索引,我们通过列表索引取的值是字符串!
正则表达时在数据的分析处理上运用挺多的,匹配查找字符还是不错的。
常见错误
IndexError: list index out of range
在操作容器类型时,大家遇到最多的可能就是索引越界问题。特别是在复杂的算法中,我们的索引绑定着各种变量,是非常容易出错的,建议各位在使用变化的索引时留做记录。
总结
不知道大家喜欢那种方式呢,适合自己的才是最好的方法哟!以上仅仅简单介绍了几种简单的解题方案,大家可以根据自己的思维创造出更好的方法,自己的方法在工作中效率更快哦。