思路
检测链表相交问题,如果能够想清楚题目核心的话就非常简单,不需要用任何指针、结构体,输入中给出的字符也完全用不上。
定义一个数组int word[100000],五位地址,因此数组大小为10的6次方即可,全部初始化为-1,代表NULL。下标代表当前单元地址,数组的实际内容代表指向的下一个单元地址。这样就简简单单地实现了链表。
求两个链表是否相交,也不需要进行时间复杂度的暴力求解,这样会超时,也没有必要。
再定义一个数组bool mark[100000],从第一个单词的首地址开始,循环遍历链表,找到最末一个地址(word[i]==-1),期间走过的i,全部将mark[i]置true,这样mark中记录的就是第一个单词所使用的所有节点。代码如下:
int tmp = w1; //w1是第一个单词的首地址
mark[w1] = true;
while (word[tmp] != -1) //如果没有到末尾,则继续向下走
{
tmp = word[tmp]; // 找到下一个地址
mark[tmp] = true;
}
最后,从第二个单词的首地址开始,循环遍历链表,期间每朝下走一步就判断mark[i]的值,为true,代表找到了相同后缀的开始地址。到最后也没有找到的话,输出-1。
坑点
中间有一个用例过不了。是因为用例中有的不是给出首地址!!!而是给的-1!!!代表着这个单词是空的!!!
题目中没说有这种情况,而如果信任测点,认为他们确实给出的是非空的首地址,那就很难找到这个问题了。
因此,加上如下判断:
int w1, w2, n;
scanf("%d %d %d", &w1, &w2, &n);
if (w1 == -1 || w2 == -1)
{
printf("-1\n");
return 0;
}
AC代码
找上面那个错误测点的问题找了半天,所以最后代码改的有点乱。
#include<stdio.h>
#define N 100000
int word[N];
bool mark[N];
int main()
{
for (int i = 0; i < N; i++)
{
word[i] = -1;
}
for (int i = 0; i < N; i++)
{
mark[i] = false;
}
int w1, w2, n;
scanf("%d %d %d", &w1, &w2, &n);
if (w1 == -1 || w2 == -1)
{
printf("-1\n");
return 0;
}
int a, b;
char c;
for (int i = 0; i < n; i++)
{
scanf("%d %c %d", &a, &c, &b);
word[a] = b;
}
int tmp = w1;
mark[w1] = true;
while (word[tmp] != -1)
{
tmp = word[tmp];
mark[tmp] = true;
}
tmp = w2;
if (mark[w2])
{
printf("%05d\n", w2);
}
else
{
bool flag = false;
while (word[tmp] != -1)
{
tmp = word[tmp];
if (mark[tmp] == true)
{
printf("%05d\n", tmp);
flag = true;
break;
}
}
if (!flag)
{
printf("-1\n");
}
}
return 0;
}