1032 Sharing (25 分)(链表)

本文探讨了PAT算法题中关于链表共享后缀的问题,介绍了一种高效解决方案,利用节点标记来快速定位两个链表的共同后缀起始位置。通过对比两种解题思路,详细解析了正确代码实现,旨在帮助读者掌握此类问题的解决技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1032 Sharing (25 分)(链表)

To store English words, one method is to use linked lists and store a word letter by letter. To save some space, we may let the words share the same sublist if they share the same suffix. For example, loading and being are stored as showed in Figure 1.

fig.jpg
Figure 1

You are supposed to find the starting position of the common suffix (e.g. the position of i in Figure 1).

Input Specification:

Each input file contains one test case. For each case, the first line contains two addresses of nodes and a positive N (≤10​5​​ ), where the two addresses are the addresses of the first nodes of the two words, and N is the total number of nodes. The address of a node is a 5-digit positive integer, and NULL is represented by −1.

Then N lines follow, each describes a node in the format:

Address Data Next

whereAddress is the position of the node, Data is the letter contained by this node which is an English letter chosen from { a-z, A-Z }, and Next is the position of the next node.

Output Specification:

For each case, simply output the 5-digit starting position of the common suffix. If the two words have no common suffix, output -1 instead.

Sample Input 1:
11111 22222 9
67890 i 00002
00010 a 12345
00003 g -1
12345 D 67890
00002 n 00003
22222 B 23456
11111 L 00001
23456 e 67890
00001 o 00010
Sample Output 1:
67890
Sample Input 2:
00001 00002 4
00001 a 10001
10001 s -1
00002 a 10002
10002 t -1
Sample Output 2:
-1
分析

自己的思路:
按照此类链表的常规题(PAT中似乎经常在第二题或者第三题考这类题,即给出链表的地址和结点然后让我们求链表的反转、排序,.etc),按照链表地址的顺序将链表节点的值收集到string中,然后将两个string逆序,遍历两个逆序的string,找到第一个不相同的节点为止,思路没问题,最后提交上去最后一个测试点无法通过。

查阅liuchuo的博客1,发现思路非常奇特,具体地是,将所有的节点存在node数组中,并且将flag设置为false,在遍历第一个链表时,将此链表的节点的flag设置为true,在遍历第二个链表时查询节点的flag值,若发现flag为true,这此节点即为要找的共同后缀的起点,在遍历第一个链表的时候,已经将node中属于第一个链表的节点标记出来,当第二个节点访问到true节点的时,表明访问到了既属于第一个链表的节点有属于第二个链表的节点,很容易理解,两个链表的初次交汇点即为共同后缀的起点。

注1:

题目要求的地址是位数,在最终输出的时候可能位数不齐,则要用0补齐,这个容易疏忽*

正确代码:

#include <iostream>
using namespace std;
struct {
    char key;
    int next;
    bool flag;
}node[100010];
int main(){
    int d1,d2,n;
    cin>>d1>>d2>>n;
    for(int i=0;i<n;i++){
        int t1,t2;
        char ch;
        cin>>t1>>ch>>t2;
        node[t1]={ch,t2,false};
    }
    for(int i=d1;i!=-1;i=node[i].next) node[i].flag=true;
    for(int i=d2;i!=-1;i=node[i].next) {
        if(node[i].flag){
            printf("%05d",i);
            return 0;
        }
    }
    printf("-1");
    return 0;
}

未正确代码:

#include <iostream>
using namespace std;
struct {
    char key;
    int next;
    bool flag;
}node[100010];
int main(){
    int d1,d2,n;
    cin>>d1>>d2>>n;
    for(int i=0;i<n;i++){
        int t1,t2;
        char ch;
        cin>>t1>>ch>>t2;
        node[t1]={ch,t2,false};
    }
    for(int i=d1;i!=-1;i=node[i].next) node[i].flag=true;
    for(int i=d2;i!=-1;i=node[i].next) {
        if(node[i].flag){
            printf("%05d",i);
            return 0;
        }
    }
    printf("-1");
    return 0;
}

  1. https://www.liuchuo.net/archives/2113 ↩︎

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值