链表是否存在环

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/king_qg/article/details/80914900

链表环的问题有两种,一种是判断是否存在环,另一种是在有的基础上返回入环的第一个节点。

简单思路:

    1、遍历链表,如果遇到空,那么肯定无环。

    2、在遍历的过程中,每个节点都加入到哈希表中,加入前判断是否存在,如果存在的话那么就有环,而且第一个判断存在的节点就是入环的第一个节点。

    总结:这个比较简单,既可以做到第一种问题,也可以做到第二种问题。但是用到了额外空间。

下面说一下另一个思路,使用快慢指针。针对两个问题分别讨论,基本上思路都是一致的。

问题一:

    思路:

        1、遍历链表,如果遇到空,那么肯定无环。

        2、在遍历过程中,如果快慢指针相遇那么就存在环。

    总结:如果没有环肯定会因为第一个条件终止,有环就会满足第二个条件。

class Solution {
public:
    bool hasCycle(ListNode *head) {
        
        if( (head == NULL) || (head->next == NULL) ){
            return false;
        }
        
        ListNode* f = head;
        ListNode* s = head;
        
        while( (f != NULL) &&  (f->next != NULL) ){
            f = f->next->next;
            s = s->next;
                
            if( f == s ){
                return true;
            }
        }
        
        return false;
    }
};

问题二:

    思路:

        和问题一相同,在问题一的基础上,如果发现有环那么快指针回到头结点,快指针变为一次走一步,再次和慢指针相遇的时候快慢指针都指向了入环的第一个节点。

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        if((head == NULL) || (head->next == NULL))
            return NULL;
        
        ListNode *slow = head;
        ListNode *fast = head;
        bool exist = false;
        while((fast != NULL) && (fast->next != NULL)){
            slow = slow->next;
            fast = fast->next->next;
            if(slow == fast){
                exist = true;
                break;
            }  
        }
        
        if( exist ){
            fast = head;
            while( fast != slow ){
                fast = fast->next;
                slow = slow->next;
            }
            return fast;
        }   
        return NULL;
    }
};

猜你喜欢

转载自blog.csdn.net/king_qg/article/details/80914900