大厂经典编程题

编程经典题-报文重排序



前言

最近笔者碰到一些有趣的编程题目,题意既贴近日常生活又引人思考,很适合大家做练手,增强编程思维。下面分享出具体题目和几种解题方法。


题目:报文重排序

对报文进行重传和重排序是常用的可靠机制,重传缓存区内有一定数量的子报文,每个子报文在原始报文中的顺序已知,现在需要恢复出原始报文。

  • 输入描述

输入第一行为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

在操作容器类型时,大家遇到最多的可能就是索引越界问题。特别是在复杂的算法中,我们的索引绑定着各种变量,是非常容易出错的,建议各位在使用变化的索引时留做记录。

总结

不知道大家喜欢那种方式呢,适合自己的才是最好的方法哟!以上仅仅简单介绍了几种简单的解题方案,大家可以根据自己的思维创造出更好的方法,自己的方法在工作中效率更快哦。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值