Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
力扣141. 环形链表
一、题目描述:
给你一个链表的头节点 head ,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。
如果链表中存在环 ,则返回 true 。 否则,返回 false 。
示例 1:
输入:head = [3,2,0,-4], pos = 1 输出:true 解释:链表中有一个环,其尾部连接到第二个节点。 示例 2:
输入:head = [1,2], pos = 0 输出:true 解释:链表中有一个环,其尾部连接到第一个节点。 示例 3:
输入:head = [1], pos = -1 输出:false 解释:链表中没有环。
提示:
链表中节点的数目范围是 [0, 104] -10^5 <= Node.val <= 10^5 pos 为 -1 或者链表中的一个 有效索引 。
进阶:你能用 O(1)(即,常量)内存解决此问题吗?
来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/li… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
二、思路分析:
-
这道题考察了什么思想?你的思路是什么?
这道题目如果用哈希表还是比较容易的,只要是有环,就一定会获取到重复的值。但是空间复杂度有点高。题目中进阶要求是用 O(1)(即,常量)内存解决此问题。所以我们需要用到Floyd 判圈算法,就是跑得快的在前面,而跑得慢的起点在后面,如果跑得慢的还能和跑得快的相遇,那么肯定是有圈了!
-
做题的时候是不是一次通过的,遇到了什么问题,需要注意什么细节?
不是一次通过的,刚开始写的时候忘记了写head = head.next; 🍵。
-
有几种解法,哪种解法时间复杂度最低,哪种解法空间复杂度最低,最优解法是什么?其他人的题解是什么,谁的效率更好一些?用不同语言实现的话,哪个语言速度最快?
看别人的题解看到了一种比较好的方法——Floyd 判圈算法,即龟兔赛跑算法。
这个算法我在实现的时候,刚开始未考虑head或head->next为空的情况,导致出错。
三、AC 代码:
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public boolean hasCycle(ListNode head) {
Set<ListNode> set = new HashSet<ListNode>();
while(head != null){
if(set.add(head) == false){
return true;
}
head = head.next;
}
return false;
}
}
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
bool hasCycle(struct ListNode *head) {
if(head == NULL || head->next == NULL) return false;
struct ListNode *slow = head;
struct ListNode *fast = head->next;
while(slow!=fast){
if(fast==NULL || fast->next==NULL){
return false;
}
slow = slow->next;
fast = fast->next->next;
}
return true;
}
四、总结:
Floyd 判圈算法得好好了解,以后遇到需要判圈的问题可以用这个方法。