這篇文章主要是分析一下鏈表是否有環問題(LeetCode141題)主要方法類似於上一篇文章
https://blog.csdn.net/you558/article/details/102409450
題目描述如下:
思路一:
遍歷鏈表,利用一個哈希表保存遍歷到的節點地址,同時判斷該節點的下一個節點是否在保存的哈希表中,若存在,則說明鏈表有環;反之,若遍歷到某一節點爲nullptr
,則說明鏈表無環。
具體實現代碼如下:
/**
* 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) {
ListNode* p=head;
unordered_set<ListNode*>sl;
while(p!=nullptr&&p->next!=nullptr)
{
sl.insert(p);
auto ret=sl.find(p->next);
if(ret!=sl.end())return true;
p=p->next;
}
return false;
}
};
思路二:
具體實現步驟如下
- 定義兩個指針slow 和fast,分別指向head和head的下一個節點
- 開始遍歷,slow每次移動一個節點,fast每次移動兩個節點
- 若fast=slow,且不爲
nullptr
,說明鏈表有環
說明:
如果鏈表有環,那麼經過若干次移動後,slow和fast兩個指針必然進入整個鏈表的環形區域(可以將其想象成圓周跑道上的兩個運動員,速度一快一慢),slow每次移動一步,fast每次移動兩步,也就是fast離slow的距離每次減小1,若干次迭代後必然相遇。
具體實現:
/**
* 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==0||head->next==0)return false;
ListNode *slow=head,*fast=head->next;
while(fast!=0&&fast->next!=0)
{
fast=fast->next->next;
slow=slow->next;
if(fast==slow)return true;
}
return false;
}
};
總結:以上兩種方法顯然第二種較優,其空間複雜度爲O(1);;兩種方法的時間複雜度均爲O(n);