环形链表I和II

环形链表I 

题目描述

给你一个链表的头节点 head ,判断链表中是否有环。如果链表中存在环,则返回true。否则,返回false 。

环形链表I和II_第1张图片

解题思路

采用快慢指针的思想,创建fast和slow一快一慢指针,slow一次走一步,fast一次走两步,如果存在环形结构,那么fast必然先进入环形,slow后进入环形,但是slow早晚也会进入环形,当快慢指针同时进入环形时,假设他们之间的距离差为N,由于slow一次走一步,fast一次走两步,fast每次比slow多走一步,他们之间的距离就会少1,因此,快慢指针必然在环形的某个位置相遇。如果能够相遇,那么必然存在环形结构。如果走着走着,fast指针为空,那么肯定不存在环形结构,因为环形结构不会出现fast为空指针的情况。

实现代码如下:

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;
}

环形链表II

 题目描述

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

解题思路

先利用环形链表I中的的思路,找到相遇点,然后让一个指针从头开始走,另一个指针从环形链表I中中的相遇点开始走,当他们相遇时,相遇点就是开始入环点,具体的原理如下图:

环形链表I和II_第2张图片

所以,一定会在入口点相遇。

具体实现代码如下:

struct ListNode *detectCycle(struct ListNode *head) 
{
    struct ListNode *fast=head;
    struct ListNode *slow=head;
    struct ListNode *meet=NULL;
    while(fast && fast->next)
    {
        fast=fast->next->next;
        slow=slow->next;
        //找到相遇点
        if(fast == slow)
        {
            meet=fast;//相遇点
            //定义一个从头开始走的结点
            struct ListNode *start=head;
            while(meet != start)
            {
                meet=meet->next;
                start=start->next;
            }
            return start;
        }
    
    }
    return NULL;   
}

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