考研数据结构(每日一题)day22

138 阅读2分钟

考研数据结构(每日一题)

题目:假定采用带头结点的单链表保存单词,当两个单词有相同的后缀时,可共享相同的后缀存储空间,例如,“loading”和“being”的存储映像如下图:

Snipaste_2022-03-16_10-07-18.png 设str1和str2分半指向两个单词所在单链表的头结点,链表结点结构为

Snipaste_2022-03-16_09-55-32.png

请设计一个时间上尽可能高效的算法,找出由str1和str2所指向两个链表共同后缀的起始位置(如图中字符i所在结点的位置p)

算法思想:

采用双指针法。用指针p、q分别扫描str1和str2,当p、q指向同一个地址时。即可找到共同后缀的起始位置。

注意:这个题目的含义是现在这种结构已经存在了,让你去判断这个起始位置在哪。而不是说给你两个单词序列,让你判断这个起始位置在哪。

算法详细步骤:

第一步:分别求出str1和str2所指的两个链表的长度m和n

第二步:将两个链表的表尾对齐:令指针p和q分别指向str1和str2的头结点,若m>=n,则p往后走,使p指向链表中第m-n+1个结点;若m<n,使q指向链表中第n-m+1个结点。将p和q所指结点到表尾的长度相等。

第三步:重复将p和q同步向后移动,当p和q指向同一位置时停止

完整代码:

typedef struct Node{     //定义结构体
    char data;
    struct Node *next;
}SNode;
//求链表长度
int listlen(SNode *head){
    int len = 0;
    while(head -> next != NULL){
        len ++;
        head = head -> next;
    }
    return len;
}
//找出共同后缀的起始地址
SNode* find_add(SNode *str1,SNode *str2){
    int m,n;
    SNode *p,*q;
    m = listlen(str1);     //求str1的长度
    n = listlen(str2);      //求str2的长度
    for(p = str1;m > n;m --){  //若m>n,则p指向链表中第m-n+1个结点
        p = p -> next;   //使p指向的链表与q指向的链表等长
    }
    for(q = str2;m < n;n --){    //若m<n,则q指向链表中第n-m+1个结点
        q = q -> next;   //使q指向的链表与p指向的链表等长
    }
    while(p -> next != NULL && p -> next != q -> next){ //将指针p和q同步向后移动
        p = p -> next;
        q = q -> next;
    }
    return p -> next;   //返回共同后缀的起始地址
}

时间复杂度为O(len1+len2)