环形链表 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;
}
};