判断两个链表是否相交,若相交,求第一个交点

该博客探讨了如何判断两个链表是否相交,并在相交时找出第一个交点。考虑了链表可能带环或不带环的三种情况,对于带环链表,分析了环内和环外相交的不同情形。

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

首先,判断这两个链表各自是否带环。故存在下面三种情况:
1、两个链表都没带环,此时两个链表可能相交。
2、一个带环,一个不带环,则不可能相交。
3、两个都带环,判断第一个链表fast与slow相遇的结点是否在第二个链表的环中,如果在,则相交(相交时,环是两个链表公有的)

两个链表都没环,解法如下:

//判断两个无环单链表是否相交,如果两个无环但链表相交,则两个链表的最后一个结点一定相等。
bool IsCross(Node* head1, Node* head2)
{
    Node* node1 = head1;
    Node* node2 = head2;
    if (head1 == NULL || head2 == NULL)
        return false;
    //找两个链表的最后一个结点
    while (node1->_next != NULL)
        node1 = node1->_next;
    while (node2 ->_next!= NULL)
        node2 = node2->_next;
    if (node1 == node2)
        return true;
    else
        return false;

}
//求链表的大小
int size(Node* head)
{
    Node* node = head;
    int count = 0;
    if (head == NULL)
        return 0;
    else
    {
        while (node)
        {
            count++;
            node = node->_next;
        }
    }
    return count;
}
//两个无环单链表相交的第一个交点。先求两个链表的长度,然后求长度差len,让较长的链表先走len步,然后找相同的结点。
Node* FindNode(Node* head1, Node* head2)
{
    if (head1 == NULL || head2 == NULL)
        return NULL;
    Node* node1 = head1;
    Node* node2 = head2;
    int len1 = size(head1);
    int len2 = size(head2);
    int len = 0;
    len = len1 - len2;
    if (len > 0)
    {
        while (len--)
        {
            node1 = node1->_next;
        }
    }
    else if (len<0)
    {
        len = 0 - len;
        while (len--)
        {
            node2 = node2->_next;
        }
    }
    //len==0
    while (node1 != node2)
    {
        node1 = node1->_next;
        node2 = node2->_next;
    }
    return node1;
}

如果两个链表都带环,解法如下:

有两种情况,如下:
入口点相同,环内相交
这里写图片描述
入口点不同,环外相交,Y形
这里写图片描述

//找带环链表内快慢指针相遇点
Node* MeetNode(Node* head)
{
    if (head == NULL)
        return NULL;
    Node* slow = head;
    Node* fast = head->_next;
    while (fast && fast->_next)
    {

        slow = slow->_next;
        fast = fast->_next->_next;
        if (slow == fast)
        {
            return slow;
        }
    }
    return NULL;
}
//找带环链表的入口点
Node* EntryNode(Node* head)
{
    if (head == NULL)
        return NULL;
    Node* slow = head;
    Node* fast = head;
    while (fast && fast->_next)
    {
        slow = slow->_next;
        fast = fast->_next->_next;
        if (slow == fast)
            break;
    }
    Node* start = head;
    while (start != slow)
    {
        start = start->_next;
        slow = slow->_next;
    }
    return start;
}
//判断两个带环链表是否相交,若相交,求交点,否则返回空
Node*  IsHasCircle(Node* head1, Node* head2)
{
    if (head1 == NULL || head2 == NULL)
        return NULL;
    //入口点相同,Y形,判断环外是否相交
    Node* ENode1 = EntryNode(head1);
    Node* ENode2 = EntryNode(head2);
    Node* m1 = MeetNode(head1);
    Node* m2 = MeetNode(head2);
    if (ENode1 == ENode2)
    {
        Node* start1 = head1;
        Node* start2 = head2;
        while (start1 != ENode1 &&start2 != ENode2)
        {       
            start1 = start1->_next;
            start2 = start2->_next;
            if (start1 == start2)
                return start1;
            else
                return NULL;
        }
    }
    //入口点不同,判断环内是否相交
    else
    {
        while (m1->_next != m2)
        {
            if (m1 == m2)
                return m1;
            m1 = m1->_next;
        }
        if (m1 == m2)
            return m1;
    }
    return NULL;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值