环形链表题

发布于:2024-05-01 ⋅ 阅读:(36) ⋅ 点赞:(0)

1.环形链表1

看题:. - 力扣(LeetCode)

思路1:哈希表

遍历所有节点,每次遍历一个节点时,判断该节点是否被访问过。

可以使用哈希表来存储所有已经访问过的节点。每次到达一个节点,如果该节点已经存在于哈希表中,则说明该链表是环形链表,否则就将该节点加入哈希表中。重复这一过程,直到我们遍历完整个链表。

思路2:快慢指针

创建两个指针,一个快指针一个慢指针,快指针一次走两步,慢指针一次走一步,如果是环形链表则两个指针会相遇,所以每走一次判断两个指针是否相等。如果不是环形链表则快指针会走到NULL。

1.1.快慢指针

看图:

代码实现:

bool hasCycle(struct ListNode *head) {
    struct ListNode *fast=head;
    struct ListNode *slow=head;
    while(fast&&fast->next)
    {
        fast=fast->next->next;
        slow=slow->next;
        if(fast==slow)
        {
            return true;
        }
    }
    return false;
}

2.环形链表2

看题:. - 力扣(LeetCode)

目录

1.环形链表1

1.1.快慢指针

2.环形链表2


思路1:快慢指针

先上结论:下面是一个环形链表,node结点位是快慢指针相遇的位置结点,phead是入环结点。

其中L的长度等于M的长度,知道这个结论后代码就信手拈来了。

下面是证明L=M:

如果是环形链表那么两个指针会相遇,找到相遇的节点node:

那么如图设置:head到入环的结点的长度为L,入环到相遇的结点node的长度为N,环的长度为C:

那么开始遍历链表,当然慢指针slow入环时快指针已经在环里走了至少一圈,假设为x圈,

当快慢指针相遇时,慢指针在环里面走的长度就是N,因为快指针的相对于慢指针的速度为1,所以每走一步快指针就与慢指针的距离-1,直到相遇。

此时

快指针走的路程:L+N+x*C

慢指针走的路程:L+N

因为快指针的速度是慢指针的两倍,所以路程也是慢指针的两倍。

所以:

L+N+x*C=2*(L+N)

整理一下:

L=x*C-N

处理:

L=(x-1)*C+C-N

式中当x取最小值时:L=C-N

而黑色部分长度就是C-N

此时让head遍历链表,node也开始往下走,当x取的值不是1时,node结点会一直在环里遍历,最终head和node一定会在入环结点相遇。

2.1代码
struct ListNode *detectCycle(struct ListNode *head) {
     struct ListNode *slow=head;
    struct ListNode *fast=head;
      struct ListNode *node=head;
    while(fast&&fast->next)
    {
        fast=fast->next->next;
        slow=slow->next;
        if(fast==fast)
        break;
    }
    if(fast==NULL||fast->next==NULL)
    return NULL;
    while(fast!=node)
    {
        
        fast=fast->next;
        node=node->next;
    }
    return fast;
}


网站公告

今日签到

点亮在社区的每一天
去签到