环形链表 LeetCode.141、142

环形链表 LeetCode.141

给定一个链表,判断是否存在环。

进一步:能否只使用额外 O(1)的空间?

算法
(链表,指针扫描) O(n)
用两个指针从头开始扫描,第一个指针每次走一步,第二个指针每次走两步。如果走到 null,说明不存在环;否则如果两个指针相遇,则说明存在环。
假设链表存在环,则当第一个指针走到环入口时,第二个指针已经走到环上的某个位置,距离环入口还差 x 步。
由于第二个指针每次比第一个指针多走一步,所以第一个指针再走 x步,两个指针就相遇了。
时间复杂度分析:第一个指针在环上走不到一圈,所以第一个指针走的总步数小于链表总长度。而第二个指针走的路程是第一个指针的两倍,所以总时间复杂度是 O(n)。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    bool hasCycle(ListNode *head) {
        if(!head||!head->next)    return false;
        ListNode *first=head,*second=head->next;
        while(first&&second)
        {
            if(first==second)   return true;
            first = first->next;
            second = second->next;
            if (second) second = second->next;
        }
        return false;
    }
};

环形链表II LeetCode142

给定一个链表,如果存在环,则返回环的入口;否则返回null。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        if(!head||!head->next)  return NULL;
        ListNode *first=head,*second=head;

        while(first&&second)
        {
            first=first->next;
            second=second->next;
            if(second)    second=second->next;
            else    return NULL;

            if(first==second)
            {
                first=head;
                while(first!=second)
                {
                    first=first->next;
                    second=second->next;
                }
                return first;
            }
        }
        return NULL;
    }
};
发布了48 篇原创文章 · 获赞 1 · 访问量 1809

猜你喜欢

转载自blog.csdn.net/zhongxinyun/article/details/104250287
今日推荐