2012-42

30 阅读2分钟
#include <iostream>

using namespace std;
/*
【2012 统考真题】42
假定采用带头结点的单链表保存单词,当两个单词有相同的后级时,
可共享相同的后缀存储空间,例如,loading和being.的存储映像如下图所示。
str-->l o a d i n g
   str2-->b e i n g
设str1和str2分别指向两个单词所在单链表的头结点,链表结点结构为data next
请设计一个时间上尽可能高效的算法,找出由str1和str2所指向两个链表共同后级
的起始位置(如图中字符i所在结点的位置p)。要求:
1)给出算法的基本设计思想。
2)根据设计思想,采用C或 C++或Java语言描述算法,关键之处给出注释。
3)说明你所设计算法的时间复杂度。
*/

typedef struct Node
{
    char data;
    struct Node *next;
} SNode;

// 计算链表长度
int listlen(SNode *s)
{
    int len = 0;
    while (s->next != nullptr)
    {
        len++;
        s = s->next;
    }
    return len;
}

// 找到第一个共同节点
SNode *find_Node(SNode *str1, SNode *str2)
{
    int m, n;
    m = listlen(str1); // 计算链表s1的长度
    n = listlen(str2); // 计算链表s2的长度
    SNode *p, *q;
    for (p = str1; m > n; m--)
    {
        p = p->next; // 让较长的链表先走几步
    }
    for (q = str2; m < n; n--)
    {
        q = q->next; // 让较长的链表先走几步
    }
    while (p->next != nullptr && p->next != q->next)
    {
        p = p->next;
        q = q->next;
    }
    return p->next; // 返回第一个相同的节点
}

SNode *createList(const string &str)
{
    SNode *head = new SNode;
    SNode *current = head;
    for (char ch : str)
    {
        current->next = new SNode{ch, nullptr};
        current = current->next;
    }
    return head;
}

// Definition for singly-linked list.

struct ListNode
{
    int val;
    ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};

// 代码随想录
class Solution1
{
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB)
    {
        ListNode *curA = headA;
        ListNode *curB = headB;
        int lenA = 0, lenB = 0;
        while (curA != NULL)
        { // 求链表A的长度
            lenA++;
            curA = curA->next;
        }
        while (curB != NULL)
        { // 求链表B的长度
            lenB++;
            curB = curB->next;
        }
        curA = headA;
        curB = headB;
        // 让curA为最长链表的头,lenA为其长度
        if (lenB > lenA)
        {
            swap(lenA, lenB);
            swap(curA, curB);
        }
        // 求长度差
        int gap = lenA - lenB;
        // 让curA和curB在同一起点上(末尾位置对齐)
        while (gap--)
        {
            curA = curA->next;
        }
        // 遍历curA 和 curB,遇到相同则直接返回
        while (curA != NULL)
        {
            if (curA == curB)
            {
                return curA;
            }
            curA = curA->next;
            curB = curB->next;
        }
        return NULL;
    }
};


class Solution2
{
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB)
    {
        auto p = headA, q = headB;
        while (p != q)
        {
            p = p ? p->next : headB; // 遍历链表A, 到达末尾后指向链表B的头
            q = q ? q->next : headA; // 遍历链表B, 到达末尾后指向链表A的头
        }
        return p; // 返回相交节点或者NULL
    }
};