题目:判断单链表是否有环,要求O(1)空间复杂度.
利用快慢指针,开始两个指针均指向链表head,然后循环移动,慢指针移动1步,快指针则移动2步,如果链表有环则两个指针一定会相遇。代码如下:
/**
* 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) {
// IMPORTANT: Please reset any member data you declared, as
// the same Solution instance will be reused for each test case.
if(head == NULL || head->next == NULL)return false;
ListNode *fast = head, *low = head;
while(fast != NULL && fast->next != NULL)
{
low = low->next;
fast = fast->next->next;
if(low == fast)return true;
}
return false;
}
};
当然还可以用倒转链表的方法来判断是否有环,沿着链表遍历,每次遍历把指针倒转,如果有环最后一定会回到head节点。不过这样会破坏链表结构 ,需要恢复。
/**
* 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) {
// IMPORTANT: Please reset any member data you declared, as
// the same Solution instance will be reused for each test case.
if(head == NULL || head->next == NULL)return false;
ListNode *p = head->next, *pre = head;
while(p)
{
if(p == head)return true;
ListNode* tmp = p->next;
p->next = pre;
pre = p;
p = tmp;
}
return false;
}
};
9.19更新
----------------
1. 检测linked list是否有环:用双指针追击法:
快指针fast一次走两步,慢指针slow一次走一步。如果有环,两指针必定在某一时间相遇。fast不会跳过slow。因为如果fast跳过slow,那么前一步它们必已经相遇。
代码如下:
class Solution {
public:
bool hasCycle(ListNode *head) {
if (!head||!head->next) {
return false;
}
ListNode* fast = head, *slow = head;
while (fast) {
if (!fast->next) {
return false;
}
fast = fast->next->next;
slow = slow->next;
if (fast==slow) {
return true;
}
}
return false;
}
};