相交链表+判断环型链表+求环型链表的入口节点

一.相交链表

相交链表

在这里插入图片描述

相交:两个链表从头开始遍历,尾节点一定是同一个节点。

情况一:当两个链表长度相同时:
在这里插入图片描述

情况二:当两个链表长度不同时:

在这里插入图片描述
思路:

  1. 求两个链表长度的差值gap。
  2. 让长链表先走gap个节点。
  3. 分别遍历两个链表,比较是否为同一个节点,若是则相交,否则不相交。

代码如下:

typedef struct ListNode ListNode;

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) 
{
    ListNode* la = headA;
    ListNode* lb = headB;
    int lengthA = 0, lengthB = 0;
    while(la)
    {
        lengthA++;//求链表A的长度
        la = la->next;
    }
    while(lb)
    {
        lengthB++;//求链表B的长度
        lb = lb->next;
    }
    //求链表A与链表B长度差的绝对值
    int gap = abs(lengthA - lengthB);

    //找出长链表与短链表
    ListNode* longList = headA;
    ListNode* shortList = headB;
    if(lengthB > lengthA)
    {
        longList = headB;
        shortList = headA;
    }

    //让长链表先走gap个节点
    while(gap--)
    {
        longList = longList->next;
    }

    //此时longList与shortList指针在相对的位置上(同时遍历链表为NULL)
    //判断两个链表是否相交
    while(longList && shortList)
    {
        if(longList == shortList)
        {
            //链表相交
            return longList;
        }
        //两个指针继续往后走
        longList = longList->next;
        shortList = shortList->next;
    }
    //链表不相交
    return NULL;
}

二.判断环型链表

环型链表

在这里插入图片描述

思路:快慢指针,即慢指针一次⾛一步,快指针一次走两步,两个指针从链表起始位置开始行,如果链表带环则一定会在环中相遇,否则快指针率先走到链表的未尾。

思考1:为什么快指针每次走两步,慢指针走一步可以相遇,有没有可能遇不上,请推理证明!
在这里插入图片描述

因此,在带环链表中慢指针走一步,快指针走两步最终一定会相遇。

思考2:快指针一次走3步,走4步,…n步行吗?

在这里插入图片描述
在这里插入图片描述

思考:真的存在N是奇数,C是偶数这一条件???

下面给出等式:
在这里插入图片描述

在这里插入图片描述

代码如下:

  1. 慢指针一次走一步,快指针一次走两步
typedef struct ListNode ListNode;

bool hasCycle(struct ListNode* head)
{
    ListNode* slow = head;
    ListNode* fast = head;
    while (fast && fast->next)
    {
        //慢指针一次走一步,快指针一次走两步
        slow = slow->next;
        fast = fast->next->next;
        //当慢指针 == 快指针时,有环
        if (slow == fast)
        {
            return true;
        }
    }
    //无环
    return false;
}
  1. 慢指针一次走一步,快指针一次走三步:
typedef struct ListNode ListNode;

bool hasCycle(struct ListNode *head) 
{
    ListNode* slow = head;
    ListNode* fast = head;
    while(fast && fast->next && fast->next->next)
    {
        //慢指针一次走一步,快指针一次走三步
        slow = slow->next;
        fast = fast->next->next->next;
        //当慢指针 == 快指针时,有环
        if(slow == fast)
        {
            return true;
        }
    }
    //无环
    return false;
}

三.求环型链表的入口节点

环型链表 ||

在这里插入图片描述

思路:快慢指针,快指针一次走两步,慢指针一次走一步,若为环型链表最终在环中相遇,然后让一个指针从相遇点开始走,一个指针从起点开始走,一次走一步,最终在进环处相遇。

在这里插入图片描述

代码如下:

//解:快慢指针,快指针一次走两步,慢指针一次走一步,若为环型链表最终在环中相遇
 //    然后让一个指针从相遇点开始走,一个指针从起点开始走,一次走一步,最终在进环处相遇

typedef struct ListNode ListNode;

struct ListNode* detectCycle(struct ListNode* head)
{
    ListNode* slow = head;
    ListNode* fast = head;
    while (fast && fast->next)
    {
        slow = slow->next;
        fast = fast->next->next;
        if (slow == fast)
        {
            //有环
            ListNode* meet = slow;//相遇点
            while (meet != head)
            {
                //一个指针从相遇点开始走,一个指针从起点开始走,最终一定在入环点相遇
                head = head->next;
                meet = meet->next;
            }
            return meet;//入环点
        }
    }
    return NULL;//无环
}

在这里插入图片描述

typedef struct ListNode ListNode;

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) 
{
    ListNode* la = headA;
    ListNode* lb = headB;
    int lengthA = 0, lengthB = 0;
    while(la)
    {
        lengthA++;//求链表A的长度
        la = la->next;
    }
    while(lb)
    {
        lengthB++;//求链表B的长度
        lb = lb->next;
    }
    //求链表A与链表B长度差的绝对值
    int gap = abs(lengthA - lengthB);

    //找出长链表与短链表
    ListNode* longList = headA;
    ListNode* shortList = headB;
    if(lengthB > lengthA)
    {
        longList = headB;
        shortList = headA;
    }

    //让长链表先走gap个节点
    while(gap--)
    {
        longList = longList->next;
    }

    //此时longList与shortList指针在相对的位置上(同时遍历链表为NULL)
    //判断两个链表是否相交
    while(longList && shortList)
    {
        if(longList == shortList)
        {
            //链表相交
            return longList;
        }
        //两个指针继续往后走
        longList = longList->next;
        shortList = shortList->next;
    }
    //链表不相交
    return NULL;
}

struct ListNode *detectCycle(struct ListNode *head) 
{
    ListNode* slow = head;
    ListNode* fast = head;
    while(fast && fast->next)
    {
        slow = slow->next;
        fast = fast->next->next;
        if(slow == fast)
        {
            //有环
            ListNode* meet = slow;//相遇点
            ListNode* newHead = meet->next;
            meet->next = NULL;

            return getIntersectionNode(head, newHead); 
        }
    }
    return NULL;//无环
}

相关推荐

  1. 单向环形创建与判断是否有

    2024-07-16 00:12:03       25 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-16 00:12:03       52 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-16 00:12:03       54 阅读
  3. 在Django里面运行非项目文件

    2024-07-16 00:12:03       45 阅读
  4. Python语言-面向对象

    2024-07-16 00:12:03       55 阅读

热门阅读

  1. 模板引擎是什么?

    2024-07-16 00:12:03       18 阅读
  2. vue3 学习笔记07 -- 定义响应式数据

    2024-07-16 00:12:03       18 阅读
  3. 第4章 引擎提供的着色器工具函数和数据结构

    2024-07-16 00:12:03       15 阅读
  4. 对删库跑路Say No

    2024-07-16 00:12:03       14 阅读
  5. 完全背包

    2024-07-16 00:12:03       14 阅读
  6. 【C语言】字符常量详解

    2024-07-16 00:12:03       20 阅读
  7. 力扣第六题——Z字形变换

    2024-07-16 00:12:03       18 阅读
  8. 数据结构初阶(C语言)-顺序表

    2024-07-16 00:12:03       18 阅读