1025 反转链表
题目
给定一个常数 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 (≤10^5)、以及正整数 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
解析
如果你想到了用数组下标来表示结点地址,结构体里保存数据和next,恭喜你,离AC又远了一点这题最好将三个数据都放进结构体,方便输出,不用管next到底是谁,只用输出结构体数组里边的下一个结点的地址就可以
当然这个结构体数组是经过反转后的数组
首先我们需要将乱序输入的结点根据地址和next,顺序放进结构体数组,必要的过程,可以过滤掉无效结点
然后利用reverse()反转结构体数组的元素,最后遍历一遍输出即可
答案
如何将乱序的 顺序存储起来呢?
暴力法
int SNode(int x){
for( int i = 0 ; i < 999999 ; i ++ ){
if( node[i].add == x){
return i;
}
}
}
while (a != -1){
re[i] = node[SNode(a)]; //串好放进re
a = re[i].next;
i++;
}
可以说非常暴力,就连加过的结点还遍历一遍,遗憾的是超时了

索性不在这上面优化了,重写淦~
新方法就是将结点新加一个数据保存自己位置的同时,用数组下标直接表示地址,可以不用查找O(1)时间完成排序
for(i = s ; i != -1 ; i = node[i].next){
re[a++] = node[i];
num ++ ; //num 用来计数真正在链表上的点
}
这样就可以啦,效果还不错,当然还有其他方法,这里就不写啦!

AC代码
#include <iostream>
#include<algorithm>
#include <string>
#include <stdio.h>
using namespace std;
struct Node{
int add;
int data;
int next;
}node[100001],re[100001];
int s,n,m;
int main(){
cin>>s>>n>>m;
int c=0,num = 0,k;
for(int i = 0 ; i < n ; i ++){
int add;
scanf("%d",&add);
scanf("%d%d",&node[add].data,&node[add].next);
node[add].add = add;
}
int a = 0,i;
for(i = s ; i != -1 ; i = node[i].next){
re[a++] = node[i];
num ++ ; //num 用来计数真正在链表上的点
}//优化后的
k = num;
while( k - m >= 0 && m > 0 ){
reverse( re + c * m,re + ( c + 1 ) * m );
c ++;
k = k -m;
}
for(int i = 0 ; i < num ; i ++){
if(i == num -1 ){
printf("%05d %d -1\n",re[i].add,re[i].data,re[i].next);
}else{
printf("%05d %d %05d\n",re[i].add,re[i].data,re[i+1].add);
}
}
}
这里附上用解析1中方法,模拟链表头插法实现全逆转的代码
#include <iostream>
#include<algorithm>
#include <string>
#include <stdio.h>
using namespace std;
struct Node{
int data;
int next;
}node[100000],re[100000];
int main(){
int s,n,add,m,nadd;
cin >> s >> n >> m;
for(int i = 0 ; i < n ; i ++){
scanf("%d",&add);
scanf("%d%d",&node[add].data,&node[add].next);
}
add = s;
re[s].data = node[s].data;
re[s].next = -1;
for(int i = 1 ; i <= n ;i ++){ //头插法插入re
nadd = node[add].next;
re[nadd] = node[nadd];
re[nadd].next = add;
if(nadd == -1) break;
add = nadd;
}
for(int i = add ; i != -1; i = re[i].next){
if(re[i].next == -1){
printf("%05d %d %d\n",i,re[i].data,re[i].next);
}else{
printf("%05d %d %05d\n",i,re[i].data,re[i].next);
}
}
}
仅能实现全逆转,不能分段逆转,我一度以为要成功了,但是紧接着就傻眼了,放上来供着👌

浙公网安备 33010602011771号