LeetCode 141:环形链表 Linked List Cycle

简介: 给定一个链表,判断链表中是否有环。为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。Given a linked list, determine if it has a cycle in it.

给定一个链表,判断链表中是否有环。

为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos-1,则在该链表中没有环。

Given a linked list, determine if it has a cycle in it.

To represent a cycle in the given linked list, we use an integer pos which represents the position (0-indexed) in the linked list where tail connects to. If pos is -1, then there is no cycle in the linked list.

示例 1:

输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。

img

示例 2:

输入:head = [1,2], pos = 0
输出:true
解释:链表中有一个环,其尾部连接到第一个节点。

img

示例 3:

输入:head = [1], pos = -1
输出:false
解释:链表中没有环。

img

进阶:

你能用 O(1)(即,常量)内存解决此问题吗?

Follow up:

Can you solve it using O(1) (i.e. constant) memory?

解题思路:

​ 从头节点向后遍历整个链表只要遍历到节点为 null ,就证明不是环形,而如果遍历到一个节点的地址之前存在过就证明有环。

1、哈希表:

解决重复问题最容易想到的数据结构就是哈希表,哈希表添加节点时只要发现节点已经存在了,证明就有环形链表。并且哈希表查找和插入复杂度都为O(1),但是空间复杂度会随着原链表长度而增大:O(n),总的来说:

  • 时间复杂度:O(n),虽然哈希表的查找和添加操作的时间复杂度是 O(1) ,但是先需要遍历链表然后插入,遍历的复杂度是O(n)
  • 空间复杂度:O(n),最多需要保存链表的 n个节点

2、双指针:

这道题就如同小学跑步问题,假设有两个人(双指针)一个快一个慢,不停地向前跑,如果跑得快的那个最后到终点了(遇到空节点 null),就证明是直线跑道(没有环形链表)。

如果是存在环形跑道(环形链表):两个人一起跑步(双指针)一个快一个慢,那么这两个人因为速度不同,在环形跑道里跑得快的那个人一定会追上慢的。即两个指针相遇了,证明存在环形链表。

空间复杂度为O(1),即进阶要求的常量内存。

哈希表解题:

Java:

public class Solution {
    public boolean hasCycle(ListNode head) {
        if (head == null) return false;//如果是空链表直接返回
        Set<ListNode> nodeSet = new HashSet<>();//构造哈希表
        while (head.next != null) {//链表下一个不为空
            if (nodeSet.contains(head)) return true;//哈希表包含该节点则存在环形链表
            nodeSet.add(head);//加入节点
            head = head.next;//下移一位
        }
        return false;
    }
}

Python:

class Solution(object):
    def hasCycle(self, head):
        """
        :type head: ListNode
        :rtype: bool
        """
        if head is None:
            return False
        hashSet=set()#构造集合
        while(head.next is not None):
            if head in hashSet:#是否已存在
                return True
            hashSet.add(head)
            head=head.next
        return False

双指针解题:

Java:

public class Solution {
    public boolean hasCycle(ListNode head) {
        if (head == null || head.next == null) {
            return false;
        }
        ListNode slow = head;
        ListNode fast = head;
        while (fast != null && fast.next != null) {//快指针及其下一位是否为空
            slow = slow.next;
            fast = fast.next.next;
            if (slow == fast) {//如果相遇,存在环形链表
                return true;
            }
        }
        return false;
    }
}

Python:

class Solution(object):
    def hasCycle(self, head):
        """
        :type head: ListNode
        :rtype: bool
        """
        if head is None or head.next is None:
            return False
        slow, fast = head, head
        while fast is not None and fast.next is not None:
            slow, fast = slow.next, fast.next.next
            if slow == fast:
                return True
        return False

扩展:

python 中is 与 == 区别 :

is 用于判断两个变量引用对象(即内存地址)是否为同一个, == 用于判断引用变量的值是否相等。

而Python出于对性能的考虑,不可变对象、同一代码块中的对象、值相同的对象,都不会重复创建,而是直接引用已经存在的对象。

欢迎关注公众号:爱写bug,一起学习。

目录
相关文章
|
8月前
【力扣】-- 移除链表元素
【力扣】-- 移除链表元素
93 1
|
8月前
Leetcode第21题(合并两个有序链表)
这篇文章介绍了如何使用非递归和递归方法解决LeetCode第21题,即合并两个有序链表的问题。
111 0
Leetcode第21题(合并两个有序链表)
|
2月前
|
算法 Go
【LeetCode 热题100】23:合并 K 个升序链表(详细解析)(Go语言版)
本文详细解析了 LeetCode 热题 23——合并 K 个升序链表的两种解法:优先队列(最小堆)和分治合并。题目要求将多个已排序链表合并为一个升序链表。最小堆方法通过维护节点优先级快速选择最小值,;分治合并则采用归并思想两两合并链表。文章提供了 Go 语言实现代码,并对比分析两种方法的适用场景,帮助读者深入理解链表操作与算法设计。
101 10
|
8月前
LeetCode第二十四题(两两交换链表中的节点)
这篇文章介绍了LeetCode第24题的解法,即如何通过使用三个指针(preNode, curNode, curNextNode)来两两交换链表中的节点,并提供了详细的代码实现。
85 0
LeetCode第二十四题(两两交换链表中的节点)
|
8月前
Leetcode第十九题(删除链表的倒数第N个节点)
LeetCode第19题要求删除链表的倒数第N个节点,可以通过快慢指针法在一次遍历中实现。
85 0
Leetcode第十九题(删除链表的倒数第N个节点)
|
8月前
|
索引
力扣(LeetCode)数据结构练习题(3)------链表
力扣(LeetCode)数据结构练习题(3)------链表
183 0
|
8月前
【LeetCode 10】142. 环形链表 II
【LeetCode 10】142. 环形链表 II
60 0
|
9月前
|
Unix Shell Linux
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
本文提供了几个Linux shell脚本编程问题的解决方案,包括转置文件内容、统计词频、验证有效电话号码和提取文件的第十行,每个问题都给出了至少一种实现方法。
128 6
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
|
10月前
|
Python
【Leetcode刷题Python】剑指 Offer 32 - III. 从上到下打印二叉树 III
本文介绍了两种Python实现方法,用于按照之字形顺序打印二叉树的层次遍历结果,实现了在奇数层正序、偶数层反序打印节点的功能。
107 6
|
10月前
|
搜索推荐 索引 Python
【Leetcode刷题Python】牛客. 数组中未出现的最小正整数
本文介绍了牛客网题目"数组中未出现的最小正整数"的解法,提供了一种满足O(n)时间复杂度和O(1)空间复杂度要求的原地排序算法,并给出了Python实现代码。
223 2