1025 反转链表 (25 分)

题目链接:

https://pintia.cn/problem-sets/994805260223102976/problems/994805296180871168

思路:

首先审题,由于地址是手动输入的缘故,本题采用数组的方式更为简单,每一个节点可以看成数组内的元素,采用结构体数组的方式进行链表数据的存储,在最初存储链表时,每一个数据的地址作为其在数组中的位置,方便后续进行查找。

设计两个结构体数组a[],b[],结构体内元素包括:address,data,next;

数组a用来存储输入的数据,数组b则用来整理数据以及翻转,在这里需要注意支节点的问题,因为链表会有游离在外的节点,使用sum进行统计一个完整的链表上节点的个数。

本题的翻转可以采用reverse()方法进行翻转,简单又快捷;

还需要注意的是翻转的次数,翻转距离为K,链表的数据量为sum,数组下标i在每次循环时要+K,循环量j要小于sum/K,(也就是算sum中有几个K啦,小学数学问题);

最后再进行输出,注意输出格式就可以了。

填坑日记:

多日不见的碎碎念,没错我又回来了。。。

好久不写代码感觉整个人都懵,这题其实挺有意思的,用数组解的话考到的不仅是数组+结构体,还有你对链表的理解程度,在使用翻转函数之后,结构体数组内的地址并不会随之改变(毕竟结构体数组里面的next不是真的next),需要我们手动进行指向的改变,(我之前就是没注意到这一点,死活不ac,用链表用多了就不太注意地址需要自己改变的这个事情了),ac之后感觉自己代码又臭又长哈哈哈哈,结构体里面放两个变量就可以了,Address不需要加进去,毕竟数据a的下标就是Address了没必要再用一个空间去存储,浪费啊。

再是有关测试点的问题(正经脸),

测试点0~4感觉就是常规测试点,把测试用例通过了基本都能过;

第5个测试点则是大量的数据,边界测试一类的,可能有游离在外的节点的情况(因为我把支节点问题解决之后,5,6都通过了);

测试点6就是考察存在支节点的问题,呜呜呜就是这个,坑了我半个上午,也是因为我太久没写代码脑袋都生锈了的缘故吧(卑微)。

代码:

#include<iostream>
#include<algorithm> 
using namespace std;
typedef struct LinkList{
	int Address;
	int Number;
	int Next;
}List;
List a[100001];
List b[100001];
void answer(){
	int A,K,N,address,number,next,i;
	scanf("%d%d%d",&A,&N,&K);
	for(i=0;i<N;i++){//写入 
		scanf("%d%d%d",&address,&number,&next);
		a[address].Address=address;
		a[address].Number=number;
		a[address].Next=next;
	}
	b[0]=a[A];
	int sum=1;
	for(i=1;i<N;i++,sum++){
		b[i]=a[b[i-1].Next];  //按顺序赋值 
		if(b[i].Next==-1)
		{
			sum++;
			break;
		}
	}
	for(int j=0,i=0;j<sum/K;j++){
		reverse(b+i,b+i+K);		//反转一下	
		i=i+K;
	}
	for(i=0;i<sum-1;i++){
		b[i].Next=b[i+1].Address;  //改变指向 
	}
	b[sum-1].Next=-1;
	for(i=0;i<sum;i++){
		if(b[i].Next>=0)
		printf("%05d %d %05d\n",b[i].Address,b[i].Number,b[i].Next);
		else
		printf("%05d %d %d\n",b[i].Address,b[i].Number,b[i].Next);
	}
}
int main(){
	answer();
	return 0;

}

下面进行膜拜大佬代码的环节:

因为大佬的代码太好了,我进行了购买,在这里就不去找网上的链接了(捂脸),没错,我买的是柳大神的,想看她博客的同学可以在我以前的博客里找,我放了链接。

代码:

​
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
    int first, k, n, temp;
    cin >> first >> n >> k;
    int data[100005], next[100005], list[100005];
    for (int i = 0; i < n; i++) {
    cin >> temp;
    cin >> data[temp] >> next[temp];
    }
    int sum = 0;
    while (first != -1) {
    list[sum++] = first;
    first = next[first];
    }
    for (int i = 0; i < (sum - sum % k); i += k)
    reverse(begin(list) + i, begin(list) + i + k);
    for (int i = 0; i < sum - 1; i++)
    printf("%05d %d %05d\n", list[i], data[list[i]], list[i + 1]);
    printf("%05d %d -1", list[sum - 1], data[list[sum - 1]]);
    return 0;
}

​

女神的代码果然还是这么简短清纯而又毫不做作\(^o^)/

来来来小伙伴们,现在是学习大佬代码的时间:

啊。。。这题可以直接这么解啊,用data和next数组直接进行数据的存储,他们之间对应的关系用数据的地址连接,然后用list数组存储链表数据的地址,就知道原始链表的地址顺序。

翻转的时候直接用list数组进行翻转,就不用再次更改next部分进行赋值了,因为此时list数组内存的地址就是翻转之后的地址顺序:list[0]的下一个地址是list[1],(而不会像我自己用结构体数组那样,内部内容不改变,还需要对Next进行重新赋值),输出时将list存储的地址与data数组的下标对应,就可以取出想要的数了,哇塞,真方便!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值