1.题目

​https://pintia.cn/problem-sets/994805342720868352/problems/994805460652113920​​ 静态链表,找出两条链表的首个公共结点。

2.思路

基础题。最巧妙点在于设一个int型变量flag,然后2次遍历——第一次遍历第一条链表(全部结点的flag改从false改为true),第二次遍历第二条链表,如果当前结点的flag是true则马上break跳出for循环(千万别忘了break!!),当然也可以直接return就好了。
注意点:
(1)用map容易超时;输出格式用%05d——不足5位的整数的高位补0;
(2)由于​​​scanf​​使用%c格式时是可以读入空格的,所以读入当前地址、数据、后继地址时,scanf的格式不能写成%d%c%d,而要写成%d %c %d。

3.代码

#include<cstdio>
#include<iostream>
#include<stdlib.h>
using namespace std;
const int maxn=100010;
struct Node{
char data;
int next;
bool flag;//结点是否在第一条链表中出现
}node[maxn];
int main(){
for(int i=0;i<maxn;i++)
node[i].flag=false;
int s1,s2,n;
int address,next;
scanf("%d%d%d",&s1,&s2,&n);
char data;//数据
for(int i=0;i<n;i++){
scanf("%d %c %d",&address,&data,&next);
node[address].data=data;
node[address].next=next;
}
int p;
for(p=s1;p!=-1;p=node[p].next){
node[p].flag=true;//枚举第一条链表的所有结点,令其出现次数为1
}
for(p=s2;p!=-1;p=node[p].next){
//遍历第2链表,找到第一个已经在第一条链表中出现的结点
if(node[p].flag==true)
break;
}
if(p!=-1){//如果第二条链表还没有到达结尾,说明找到了共用结点
printf("%05\n",p);
}else{
printf("-1\n");
}
system("pause");
}

4.模板总结

(1)定义静态链表。
(2)for循环对静态链表的每个结点的某元素初始化。
(3)遍历链表,计数:

int p=begin,count=0;
while(p!=-1){//-1代表链表结束
XXX=1;
count++;
p=node[p]->next;
}

(4)很多时候题目给出的结点并不都是有效结点(即可能存在不在链表上的结点),对数组进行排序从而把有效结点移到数组左端。

bool cmp(Node a,Node b){
if(a.XXX==-1||b.XXX=-1){
//至少一个结点是无效结点,就把它放到数组后面
return a.XXX>b.XXX;
}else{
//第二级排序
}
}