<---
大佬们点个赞吧qwq
题目描述
给定一个单链表 L,我们将每 K 个结点看成一个区块(链表最后若不足 K 个结点,也看成一个区块),请编写程序将 L 中所有区块的链接反转。
例如:给定 L 为 1to2to3to4to5to6to7to8,K 为 3,则输出应该为 7to8to4to5to6to1to2to3。
补充
本题中可能包含不在单链表中的节点,这些节点无需考虑。
输入格式
第 1 行给出第 1 个结点的地址、结点总个数正整数 N、以及正整数 K,即区块的大小。结点的地址是 5 位非负整数(可能包含前导 0),NULL 地址用 −1 表示。
接下来有 N 行,每行格式为:
Address Data Next
其中 Address
是结点地址,Data
是该结点保存的整数数据,Next
是下一结点的地址。
输出格式
对每个测试用例,顺序输出反转后的链表,其上每个结点占一行,格式与输入相同。
数据范围
1leKleNle105
输入样例:
00100 8 3
71120 7 88666
00000 4 99999
00100 1 12309
68237 6 71120
33218 3 00000
99999 5 68237
88666 8 -1
12309 2 33218
输出样例:
71120 7 88666
88666 8 00000
00000 4 99999
99999 5 68237
68237 6 00100
00100 1 12309
12309 2 33218
33218 3 -1
算法
(模拟) O(n)
按题意模拟即可。
注意事项
1. 并不是所有的结点都在 L 上(这个坑我帮你们踩了)
2. 最后一个区块的边界问题
3. 最后一个节点要输出-1
时间复杂度
很明显,我们在反转区块的时候每个结点只遍历了 1 次,所以时间复杂度是 O(n)。
空间复杂度
程序中开的链表长度最多为 n,所以空间复杂度也是 O(n)。
C++ 代码
#include <iostream>
using namespace std;
const int N = 100010;
int k, n, h; // h表示头结点地址
int e[N], ne[N], l[N], len_l, res[N], len_r; // e存结点保存的整数数据,ne存下一结点的地址,l存链表,res存结果,len_l存l的长度,len_r存res的长度
int main()
{
cin >> h >> n >> k;
while (n -- )
{
int addr;
cin >> addr >> e[addr] >> ne[addr]; // 读入结点
}
int i = h;
do // 初始化l
{
l[len_l ++ ] = i;
i = ne[i];
}
while (~i);
len_r = len_l; // 要倒序
for (int i = 0; i < len_l; i += k) // i表示区块开头
for (int j = min(len_l, i + k) - 1; j >= i; j -- ) // 从区块结尾开始枚举
res[ -- len_r] = l[j]; // 存到结果数组里
for (int i = 0; i < len_l; i ++ ) // 遍历
{
printf("%05d %d ", res[i], e[res[i]]);
if (i ^ len_l - 1) printf("%05d\n", res[i + 1]); // 如果这个结点不是最后一个就输出下一个结点的地址
else puts("-1"); // 否则输出-1
}
return 0;
}
顶!
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCOrz
谢谢!qwq