这篇文章主要是分析一下链表是否有环问题(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);