浙大 PAT 甲级 1032 Sharing C++ 部分错误原因

思路

检测链表相交问题,如果能够想清楚题目核心的话就非常简单,不需要用任何指针、结构体,输入中给出的字符也完全用不上。

定义一个数组int word[100000],五位地址,因此数组大小为10的6次方即可,全部初始化为-1,代表NULL。下标代表当前单元地址,数组的实际内容代表指向的下一个单元地址。这样就简简单单地实现了链表。

求两个链表是否相交,也不需要进行O(n^2)时间复杂度的暴力求解,这样会超时,也没有必要。

再定义一个数组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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值