L2-022 重排链表 (25 分)(测试点3,超级详细解析,看不懂捶我)

360 篇文章 3 订阅
88 篇文章 5 订阅

给定一个单链表 L1​​ →L2 →⋯→L​n−1​​ →L​n​​ ,请编写程序将链表重新排列为 L​n​​ →L​1​​ →L​n−1​​ →L​2​​ →⋯。例如:给定L为1→2→3→4→5→6,则输出应该为6→1→5→2→4→3。
输入格式:

每个输入包含1个测试用例。每个测试用例第1行给出第1个结点的地址和结点总个数,即正整数N (≤10​5​​ )。结点的地址是5位非负整数,NULL地址用−1表示。

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

Address Data Next
其中Address是结点地址;Data是该结点保存的数据,为不超过10
​5
​​ 的正整数;Next是下一结点的地址。题目保证给出的链表上至少有两个结点。

输出格式:

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

输入样例:

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

输出样例:

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

和之前的链表去重有一定的区别,输出的时候别被带跑偏了,具体思路是这样的:首先先将链表都输入结构体中,然后根据循环条件

	while(a[i].next!=-1){
		b1[t1++]=a[i].address;
		b2[t2++]=a[i].data;
		i=a[i].next;
	}

将排好序的链表首地址放入b1中,值放在b2中,注意这里到-1以后不循环,但是下一个地址为-1的节点还没放入数组,所以需要单独的

b1[t1++]=a[i].address;
b2[t2++]=a[i].data;

这里其实也可以用两个结构体,我这里用的是两个一维数组,是一个意思。
然后我觉得才是整个题的难点所在,怎么重排?考的时候想了半天没想出来,被前面的链表去重带跑偏了,其实不难,分析如下

while(t1--){//这里一定要用t1不能用n,因为会出现链表中有多个尾地址为-1的重复节点(无效的,无需考虑,所以t1的值是<=n的,只能用t1)
		j++;//j来判断奇数偶数,如果是奇数,就输出后面的,如果是偶数,就输出前面的
		if(j%2==1){
			if(t1==0) printf("%05d %d -1\n",b1[max],b2[max]);//等于0时特殊考虑
			else{
				printf("%05d %d %05d\n",b1[max],b2[max],b1[min]);//输出后面的地址,数值和前面的地址
				max--;//max--
				
			} 
		}
		else{
			if(t1==0) printf("%05d %d -1\n",b1[min],b2[min]);
			else{
				printf("%05d %d %05d\n",b1[min],b2[min],b1[max]);
				min++;
				
			} 
		}
	}

AC代码如下:在这里插入图片描述

#include<iostream>
#include<string>
#include<algorithm>
#include<bits/stdc++.h>
#include<stack>
#include<set>
#include<vector>
#include<map>
#include<queue>
#include<deque>
#include<cctype>
#include<unordered_set> 
#include<unordered_map> 
#include<fstream>
using namespace std;
struct Node{
	int address;
	int data;
	int next;
};
int main(){
    int first,n;
    cin>>first>>n;
    int b1[n];
    int b2[n];
    Node a[100000];
    for(int i=0;i<n;i++){
    	int address,data,next;
    	cin>>address>>data>>next;
    	a[address].address=address;
    	a[address].data=data;
    	a[address].next=next;
	}
	int i=first;
	int t1=0,t2=0; 
	while(a[i].next!=-1){
		b1[t1++]=a[i].address;
		b2[t2++]=a[i].data;
		i=a[i].next;
	}
	b1[t1++]=a[i].address;
	b2[t2++]=a[i].data;
	int j=0,min=0,max=t1-1;
	while(t1--){
		j++;
		if(j%2==1){
			if(t1==0) printf("%05d %d -1\n",b1[max],b2[max]);
			else{
				printf("%05d %d %05d\n",b1[max],b2[max],b1[min]);
				max--;
				
			} 
		}
		else{
			if(t1==0) printf("%05d %d -1\n",b1[min],b2[min]);
			else{
				printf("%05d %d %05d\n",b1[min],b2[min],b1[max]);
				min++;
				
			} 
		}
	}
	return 0;
} 

  • 10
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_努力努力再努力_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值