剑指offer 环形链表

50 阅读2分钟

141. 环形链表 I

环形链表1只要求我们判断链表当中是否有环。 思想 双指针 让快指针一次走慢指针二倍的路程,如果链表当中有环,那么快指针肯定可以追上慢指针,如果相遇 ,那么就有环。

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


}

注意事项

当链表中只要一个节点时是不合法的,应该输出false:

image.png

image.png

所以应该加一个条件,当没有下一个节点,下下个节点为空时就不进入我们的判断条件:


    while(fast&&fast->next&&fast->next->next)
    {
        fast=fast->next->next;
        slow=slow->next;
        

LCR 022. 环形链表 II

环形链表II要求我们找到环的起始节点

我们还是先判断是否有环。

如何获得环中节点个数:

image.png

获得节点个数之后怎么找到环起始点:

image.png

class Solution {
public:

ListNode* MeetingNode(ListNode* head)
    {
        
        //判断是否有环
        struct ListNode*  slow=head;
        struct ListNode* fast=head;
        while(fast&&fast->next&&fast->next->next)
        {
            fast=fast->next->next;
            slow=slow->next;
            
        if(slow==fast)
        {return fast;
        
        }
        }
        return nullptr;
        
    }



//寻找环的入口
ListNode* startMeetingNode(ListNode* head)
{
    //
    ListNode* meetingNode=MeetingNode(head);

    if(meetingNode==nullptr)return nullptr;

    //得到环中节点的数目
    int count=1;//计数器
    ListNode* PNode1=meetingNode;
    while(  PNode1->next!=meetingNode)
    {
        PNode1=PNode1->next;
        ++count;
    }


    //找环起始点
    
    //fast先走环中节点个数
    PNode1=head;
    while(count--)
    {
        PNode1=PNode1->next;
    }


    //fast再和slow同步走,相遇即到环入口
    ListNode* PNode2=head;

    while(PNode1!=PNode2)
    {
        PNode1=PNode1->next;
        PNode2=PNode2->next;
    }


return PNode1;
}




    ListNode *detectCycle(ListNode *head) {
        
        //判断是否有环
         MeetingNode( head);


         //找环的入口
         return startMeetingNode(head);


    }
};

上面代码太冗余了,可以简化为:

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode *fast = head, *slow = head;
       
       //判断是否有环
        while (true) {
            if (fast == nullptr || fast->next == nullptr) return nullptr;
            fast = fast->next->next;
            slow = slow->next;
            if (fast == slow) break;
        }



        //找环入口
        fast = head;
        while (slow != fast) {
            slow = slow->next;
            fast = fast->next;
        }
        return fast;
    }
};