给你一个链表的头节点 head ,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos
来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos
不作为参数进行传递,仅仅是为了标识链表的实际情况。如果链表中存在环,则返回 true 。 否则,返回 false 。
输入:head = [3,2,0,-4], pos = 1 输出:true 解释:链表中有一个环,其尾部连接到第二个节点。
输入:head = [1,2], pos = 0 输出:true 解释:链表中有一个环,其尾部连接到第一个节点。
输入:head = [1], pos = -1 输出:false 解释:链表中没有环。提示:
链表中节点的数目范围是 [0, 104]
-105 <= Node.val <= 105 pos 为 -1 或者链表中的一个 有效索引
思路
所谓“鬼打墙”,就是在夜晚或郊外行走时,分不清方向,自我感知模糊,不知道要往何处走,所以老在原地转圈。
1.如遇到鬼打墙的事件,不要慌张,集中一切注意力,睁大眼睛。
2.夜间行路带把手电筒就行了。
3.迷路了要问人。
4.可以根据北极星的位置来辨别方向。
5.手机GPS导航,少了很多路痴。
6.指南针,手机也有。
7.不要慌,不要迷信,有小店什么的就去吃点东西,和店长聊下,问下路,有公交站就上去转车到你知道的地方。
8.手机就算没信号,也可播放音乐给自己壮胆,心平复才能思考,但别没电了。
结合本题
1.判断是否有死循环,有死循环就有环,无死循环能顺利结束就没有环,但是人在环中,很难判断这个。有个取巧的就是节点数量限在10000内,如果循环超过这个数就有环。
2.pos没用,仅仅是让你知道这个末尾最后指向哪了,让你心里有个数,实际上完全可以不给你这个值,因为这个是定性题,不是定量的,不需要你知道是指向哪的环。
3.看题解和评论知道了哈希表解法、快慢指针解法、鬼打墙标记解法
哈希表是把遍历过的节点存在哈希表中,之后如果再次出现就说明有环`
快慢指针是 追及问题,一个快指针,一个慢指针,快的先走,如果没有环,他们肯定是不会遇到的,如果有环,快的会先进入环,这样快的总会追上慢的,所以可以判断出来。关键是怎么判断快慢指针相遇了
鬼打墙标记,和哈希表异曲同工,给遍历过的节点都指向一个特殊的节点,检测之后节点的next,如果之后的出现重复,就说明有环。
1.哈希表
class Solution {
public:
bool hasCycle(ListNode *head) {
unordered_set<ListNode*> seen;
while (head != nullptr) {
if (seen.count(head)) {
return true;
}
seen.insert(head);
head = head->next;
}
return false;
}
};
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/linked-list-cycle/solution/huan-xing-lian-biao-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
2.快慢指针
class Solution {
public:
bool hasCycle(ListNode* head) {
if (head == nullptr || head->next == nullptr) {
return false;
}
ListNode* slow = head;
ListNode* fast = head->next;
while (slow != fast) {
if (fast == nullptr || fast->next == nullptr) {
return false;
}
slow = slow->next;
fast = fast->next->next;
}
return true;
}
};
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/linked-list-cycle/solution/huan-xing-lian-biao-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
我的题解:
/**
* 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 == nullptr){
return false;
}
ListNode* s = head;
ListNode* f = head->next;
while(s){
if(s == f){
return true;
}
s = s->next;
if(f && f->next && f->next->next){
f = f->next->next;
}
else{
return false;
}
}
return false;
}
};
为什么有下面这句,因为如果是环形的就不会有->next == nullptr的情况,现在有这种情况了,说明不是环形的
但反过来却不能用来验证是环形的。
else{
return false;