《环形链表》 带环? 面试常问的这些问题你可得把握住了

环形链表在很多面试时都有出现,这里面的一些细节更是面试官喜欢考察的重点,这些技巧和细节你可得把握住了,不然就让我替你们来把握。

我们直接来看一道力扣上经典的环形链表题

给定一个链表,判断链表中是否有环。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

如果链表中存在环,则返回 true 。 否则,返回 false 。

这里我们如何判断判断链表是否有环呢?

显然我们这是用快慢指针的方法就很nice

 

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
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; //没环
}

至于为什么快指针跑两步,慢指针跑一步,如果快指针跑3步,4部,5,6,步呢?

因为快指针跑两步的话,在入环的时候二者距离不管多少,每一次移动二者距离都会逐渐缩小一步,而且一定会在慢指针的第一圈内相遇

具体的证明就留给大家自行思考了。这点还是要靠小友自己把握了。

那如果跑3,4,5,6 步呢,二者的距离虽然也在逐渐减小,但结合到环的大小,与二者逐步减少的距离,二者可能在第2,3,4圈相遇,也可能无法相遇,具体的证明需要用到一些数学知识,大家也可以在下面自己证明,这里笔者就不给出了。

学会了判断是不是环形链表了,那我们再来找找入环节点

给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。

为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意,pos 仅仅是用于标识环的情况,并不会作为参数传递到函数中。

说明:不允许修改给定的链表。

这里找进入的那个节点,这里面有点东西哈 

 《环形链表》 带环? 面试常问的这些问题你可得把握住了_第1张图片

 看完了上面简单的思路之后,我们不难发现这样一个规律

如果这时候我们再让慢指针快指针,从链表头相交点分别出发,且每次走一步,那么二者就会在入环点相遇

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode *detectCycle(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)//快慢指针
        {
            slow=head;
         while(fast!=slow)没有相遇的时候
         {
          fast=fast->next;
          slow=slow->next;
         }
         return fast;返回此时入环节点
        }
    }
    return NULL;  
}

你可能感兴趣的:(经典算法题,链表,面试,数据结构)