环形链表和相交链表OJ题

环形链表和相交链表OJ题

在这里插入图片描述

这篇博客详细讲解了环形数组和相交数组的问题

一、环形链表

环形列表是指尾结点next不指向NULL了,而是指向包括自己的前面任意一个结点。

e.g.1

题目及要求:
在这里插入图片描述
在这里插入图片描述
样例:
在这里插入图片描述
分析:
在这里插入图片描述
1.正常如果在找尾过程中,尾结点的下一个结点就是NULL,而环形链表则不是这样,所以我们可以通过这个条件来做一个初步的判断。
2.我们还是可以用快慢指针的思想(这个很重要,在很多找特定位置结点的题都可以用到这个思想),一个快指针和一个慢指针,如果相遇了,那就说明链表是一个循环的。快的可以给慢的扣圈。

代码实现:

bool hasCycle(struct ListNode *head) {
    struct ListNode* fast = head, *slow = head;
    while (fast && fast->next)//奇偶结点不同,判断条件不同
    {
        fast = fast->next->next;//快指针,后续会解释为什么用2倍速
        slow = slow->next;
        if (fast == slow)//相遇
        {
            return true;
        }
    }
    return false;
}

e.g.2

题目及要求:
在这里插入图片描述
在这里插入图片描述

样例:
在这里插入图片描述
分析:
在这里插入图片描述
结论:一个指针从起点,另一个指针从相遇点,他们同时出发,会在第一个进入循环的结点处相遇。
代码实现:

struct ListNode *detectCycle(struct ListNode *head) {
    struct ListNode* fast = head, *slow = head;
    while (fast && fast->next)
    {
        fast = fast->next->next;
        slow = slow->next;
        if (fast == slow)
        {
            struct ListNode* meet = slow;
            while (meet != head)
            {
                head= head->next;
                meet = meet->next;
            }
            return head;
        }
    }
    return NULL;
}

二、相交链表

题目及要求:
在这里插入图片描述
在这里插入图片描述

样例:
在这里插入图片描述

在这里插入图片描述
分析:
只能Y型相交,不能X型,因为一个结点向后只能存储一个地址,所以用了一个之后,后面就都是共同的结点了。
首先,我们可以考虑用A的第一个结点去和B里面每一个结点的地址比较,切记不能比结构体里的数值,因为数值可以相等。再用第二个去比,持续循环,这样最差的情况就是都找一遍还没找到,时间复杂度O(n ^ 2)。

其次,我们想一点时间复杂度更低的方式,可以找到他们等长位置的结点,一起向后走就可以了,其实这里也用到了快慢指针的思想,快慢指针就是利用中间的差值,而我们是为了将差值消掉。
代码实现:

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    struct ListNode* tailA = headA, *tailB = headB;
    int countA = 0, countB = 0;
    while (tailA->next)//既通过找到尾结点判断两个链表的尾结点是否相等
    //来判断是否相交,也能算出长度,为后续磨平长度差做铺。
    {
        tailA = tailA->next;
        countA++;
    }
    while (tailB->next)
    {
        tailB = tailB->next;
        countB++;
    }
    if (tailA != tailB)
    {
        return NULL;
    }
    else
    {
        int n = abs(countA - countB);//无论差值正负,abs都变成正数差值
        struct ListNode* longList = headA, *shortList = headB;
        if (countA < countB)
        {
            longList = headB, shortList = headA;
        }
        while (n--)//循环n次,while(--n)循环(n - 1)次
        {
            longList = longList->next;
        }
        while (longList != shortList)
        {
            longList = longList->next;
            shortList = shortList->next;
        }
        return longList;
    }
}

如果对大家有帮助的话,希望大家多多点赞关注呀!
如果文章里有什么问题,也希望大家可以为我指出,谢谢大家!

  • 10
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值