leetcode每日一题
7月
1833. 雪糕的最大数量
5801. 消灭怪物的最大数量
1418. 点菜展示表
1711. 大餐计数
5792. 统计平方和三元组的数目
274. H 指数
面试题 10.02. 变位词组
6月
1744. 你能在你最喜欢的那天吃到你最喜欢的糖果吗?
42. 接雨水
206. 反转链表
234. 回文链表
141. 环形链表
474. 一和零
5777. 使数组元素相等的减少操作次数
5776. 判断矩阵经轮转后是否一致
1897. 重新分配字符使所有字符串都相等
752. 打开转盘锁
5781. 删除一个字符串中所有出现的给定子字符串
5789. 你完成的完整对局数
5788. 字符串中的最大奇数
852. 山脉数组的峰顶索引
1894. 找到需要补充粉笔的学生编号
5786. 可移除字符的最大数目
1893. 检查是否区域内所有整数都被覆盖
1899. 合并若干三元组以形成目标三元组
5799. 最美子字符串的数目
5780. 删除一个元素使数组严格递增
5月
342. 4的幂
231. 2 的幂
560. 和为K的子数组
141. 环形链表
1074. 元素和为目标值的子矩阵数量
461. 汉明距离
1190. 反转每对括号间的子串
664. 奇怪的打印机
1787. 使所有区间的异或结果为零(放弃治疗)
1707. 与数组中元素的最大异或值
810. 黑板异或游戏
1035. 不相交的线
692. 前K个高频单词
1738. 找出第 K 大的异或坐标值
993. 二叉树的堂兄弟节点
13. 罗马数字转整数
1442. 形成两个异或相等数组的三元组数目
12. 整数转罗马数字
1269. 停在原地的方案数
1734. 解码异或后的排列
1310. 子数组异或查询
872. 叶子相似的树
vditor使用说明
645. 错误的集合
930. 和相同的二元子数组
5793. 迷宫中离入口最近的出口
5843. 作为子字符串出现在单词中的字符串数目
5832. 构造元素不等于两相邻元素平均值的数组
5851. 找出不同的二进制字符串
5850. 找出数组的最大公约数
5835. 最大方阵和
n个人匹配,两两匹配,匹配多轮
本文档使用 MrDoc 发布
-
+
首页
141. 环形链表
# 题目 ## 141. 环形链表 [https://leetcode-cn.com/problems/linked-list-cycle/](https://leetcode-cn.com/problems/linked-list-cycle/) # 题解 给定一个链表,判断链表中是否有环。 如果链表中有某个节点,可以通过连续跟踪 `next` 指针再次到达,则链表中存在环。 为了表示给定链表中的环,我们使用整数 `pos` 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 `pos` 是 `-1`,则在该链表中没有环。**注意:`pos` 不作为参数进行传递** ,仅仅是为了标识链表的实际情况。 如果链表中存在环,则返回 `true` 。 否则,返回 `false` 。 **进阶:** 你能用 *O(1)* (即,常量)内存解决此问题吗? **示例 1:** ![](/media/202105/2021-05-27_225026.png) ``` 输入:head = [3,2,0,-4], pos = 1 输出:true 解释:链表中有一个环,其尾部连接到第二个节点。 ``` **示例 2:** ![](/media/202105/2021-05-27_225026.png) ``` 输入:head = [1,2], pos = 0 输出:true 解释:链表中有一个环,其尾部连接到第一个节点。 ``` **示例 3:** ![](/media/202105/2021-05-27_225026.png) ``` 输入:head = [1], pos = -1 输出:false 解释:链表中没有环。 ``` **提示:** * 链表中节点的数目范围是 `[0, 10<sup>4</sup>]` * `-10<sup>5</sup><span> </span><= Node.val <= 10<sup>5</sup>` * `pos` 为 `-1` 或者链表中的一个 **有效索引** 。 ## 思路 快慢指针,慢指针一步步走,快指针两步,如果有相等,快慢会相遇 ## 代码 ```javascript /** * Definition for singly-linked list. * function ListNode(val) { * this.val = val; * this.next = null; * } */ /** * 快慢指针 * @param {ListNode} head * @return {boolean} */ var hasCycle = function(head) { if(!head || !head.next) return false; let slow = head; let fast = head.next; while(slow !== fast){ if(!fast || !fast.next) return false; slow = slow.next; fast = fast.next.next; } return true; }; ``` ## 官方 #### 方法一:哈希表 **思路及算法** 最容易想到的方法是遍历所有节点,每次遍历到一个节点时,判断该节点此前是否被访问过。 具体地,我们可以使用哈希表来存储所有已经访问过的节点。每次我们到达一个节点,如果该节点已经存在于哈希表中,则说明该链表是环形链表,否则就将该节点加入哈希表中。重复这一过程,直到我们遍历完整个链表即可。 **代码** ``` public class Solution { public boolean hasCycle(ListNode head) { Set<ListNode> seen = new HashSet<ListNode>(); while (head != null) { if (!seen.add(head)) { return true; } head = head.next; } return false; } } ``` **复杂度分析** - 时间复杂度:O(N),其中 N 是链表中的节点数。最坏情况下我们需要遍历每个节点一次。 - 空间复杂度:O(N),其中 N 是链表中的节点数。主要为哈希表的开销,最坏情况下我们需要将每个节点插入到哈希表中一次。 #### 方法二:快慢指针 **思路及算法** 本方法需要读者对「Floyd 判圈算法」(又称龟兔赛跑算法)有所了解。 假想「乌龟」和「兔子」在链表上移动,「兔子」跑得快,「乌龟」跑得慢。当「乌龟」和「兔子」从链表上的同一个节点开始移动时,如果该链表中没有环,那么「兔子」将一直处于「乌龟」的前方;如果该链表中有环,那么「兔子」会先于「乌龟」进入环,并且一直在环内移动。等到「乌龟」进入环时,由于「兔子」的速度快,它一定会在某个时刻与乌龟相遇,即套了「乌龟」若干圈。 我们可以根据上述思路来解决本题。具体地,我们定义两个指针,一快一满。慢指针每次只移动一步,而快指针每次移动两步。初始时,慢指针在位置 `head`,而快指针在位置 `head.next`。这样一来,如果在移动的过程中,快指针反过来追上慢指针,就说明该链表为环形链表。否则快指针将到达链表尾部,该链表不为环形链表。 **细节** 为什么我们要规定初始时慢指针在位置 `head`,快指针在位置 `head.next`,而不是两个指针都在位置 `head`(即与「乌龟」和「兔子」中的叙述相同)? - 观察下面的代码,我们使用的是 `while` 循环,循环条件先于循环体。由于循环条件一定是判断快慢指针是否重合,如果我们将两个指针初始都置于 `head`,那么 `while` 循环就不会执行。因此,我们可以假想一个在 `head` 之前的虚拟节点,慢指针从虚拟节点移动一步到达 `head`,快指针从虚拟节点移动两步到达 `head.next`,这样我们就可以使用 `while` 循环了。 - 当然,我们也可以使用 `do-while` 循环。此时,我们就可以把快慢指针的初始值都置为 `head`。 **代码** ``` public class Solution { public boolean hasCycle(ListNode head) { if (head == null || head.next == null) { return false; } ListNode slow = head; ListNode fast = head.next; while (slow != fast) { if (fast == null || fast.next == null) { return false; } slow = slow.next; fast = fast.next.next; } return true; } } ``` **复杂度分析** - 时间复杂度:O(N),其中 N 是链表中的节点数。 - 当链表中不存在环时,快指针将先于慢指针到达链表尾部,链表中每个节点至多被访问两次。 - 当链表中存在环时,每一轮移动后,快慢指针的距离将减小一。而初始距离为环的长度,因此至多移动 N 轮。 - 空间复杂度:O(1)。我们只使用了两个指针的额外空间。
czbiao
2021年5月27日 23:00
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
阅读量
次
本站总访问量
次
本站访客数
人次
Markdown文件
分享
链接
类型
密码
更新密码