PAT乙级练习题_1025“反转链表”_python解题

原题

给定一个常数 K 以及一个单链表 L,请编写程序将 L 中每 K 个结点反转。例如:给定 L 为 1→2→3→4→5→6,K 为 3,则输出应该为 3→2→1→6→5→4;如果 K 为 4,则输出应该为 4→3→2→1→5→6,即最后不到 K 个元素不反转。

输入格式

每个输入包含 1 个测试用例。每个测试用例第 1 行给出第 1 个结点的地址、结点总个数正整数 N (≤ 1 0 5 10^5 105)、以及正整数 K (≤N),即要求反转的子链结点的个数。结点的地址是 5 位非负整数,NULL 地址用 −1 表示。

接下来有 N 行,每行格式为:

Address Data Next

其中 Address 是结点地址,Data 是该结点保存的整数数据,Next 是下一结点的地址。

输出格式

对每个测试用例,顺序输出反转后的链表,其上每个结点占一行,格式与输入相同。

输入样例

00100 6 4
00000 4 99999
00100 1 12309
68237 6 -1
33218 3 00000
99999 5 68237
12309 2 33218

输出样例

00000 4 33218
33218 3 12309
12309 2 00100
00100 1 99999
99999 5 68237
68237 6 -1

my answer

有一个测试超时

思路:定义一个字典,字典中的元素都是以"Address": "Data Next"形式存储,然后通过首地址在字典中找到首元节点,再以首元节点的Next在字典中寻找首元结点的直接后继。在顺链遍历的过程中,按照要求的反转的子链表的大小N,每N个节点为一组,每个节点以元组的形式存入到列表linklist_child中,N个节点元组组成的一个列表linklist_child再放入一个大的列表linklist中,如此循环。对于最后一组子链,可能节点的数目小于N,对于这组子链不必进行反转。

当所有的节点按顺序、按组存放到linklist中之后,遍历linklist,每次取出一个子链表(子链表以列表为类型,里面存放着以元组为类型的节点信息),如果子链中结点的数目等于N,从后往前输出节点信息;如果子链中结点的数目小于N,不需要反转,直接按要求输出即可。

basicInfo = input().split()
dict_node = dict() # 定义一个空的字典,字典中以“节点的地址”为键,以“节点的值和下一个节点的地址”为值
for i in range(int(basicInfo[1])):
    node = input()
    dict_node[node[:5]] = node[6:] # 将每一个节点都存到字典中

linklist = [] # 定义一个空的列表,其中每个元素也为一个列表,每个元素代表要反转的子链表
linklist_child = [] # 该列表用于存储一个子链表,子链表中的节点信息在列表中用一个元组表示

pointer = basicInfo[0] # 定义一个“指针”,用于顺链查找
count = 0 # 计数器,每找到一个完整的子链表,count 归零
while pointer != '-1': # 当“指针”没有到达最后一个节点时
    node_info = dict_node[pointer]
    node_info_list = node_info.split()
    node_info_list.insert(0, pointer)
    linklist_child.append(tuple(node_info_list))
    pointer = node_info_list[-1]
    count += 1
    
    if count == int(basicInfo[2]): # 如果子链表的节点数到达指定数目,计数器归零,将子链表添加到 linklist 中
        count = 0
        linklist.append(linklist_child.copy()) # 注意此处不能直接 append(linklist_child),因为在下一行要执行 linklist_child.clear()
        linklist_child.clear()

# 循环完毕之后判断一下是否有剩余元素
if len(linklist_child) != 0:
    linklist.append(linklist_child)

flag = False # 表示是否打印的不是第一行
for linklistChild in linklist:
    if len(linklistChild) == int(basicInfo[2]): # 判断子链的结点数是否满足要求
        index = -1
        for i in linklistChild:
            node = linklistChild[index]
            if flag: # 如果打印的不是第一行,就打印该结点的地址(表示上一个结点的Next值)之后,换行,再打印该结点的Address、Data值
                print(node[0])
                print("{} {} ".format(node[0], node[1]), end='')
            else: # 如果打印的是第一行,就把该结点的Address、Data值并排输出
                print("{} {} ".format(node[0], node[1]), end='')
                flag = True
            index -= 1
    else:
        for node in linklistChild:
            if flag:
                print(node[0])
                print("{} {} ".format(node[0], node[1]), end='')
            else:
                print("{} {} ".format(node[0], node[1]), end='')
                flag = True
print("-1")
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值