【LeetCode题解】142_环形链表2(Linked-List-Cycle-II)
描述
给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
说明:不允许修改给定的链表。
进阶:
你是否可以不用额外空间解决此题?
解法一:哈希表
思路
最直接的解法就是利用一个集合保存每次遍历的节点的引用。之后,从链表头开始遍历,每遍历一个节点,就判断该节点的引用是否在集合中,如果不在集合中,则将该节点的引用放入集合中;如果在集合中,则返回该节点的引用(环的入口)。当然,如果能遍历到链表尾部,此时链表无环,返回 null。
Java 实现
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
import java.util.Set;
import java.util.HashSet;
public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode curr = head;
Set<ListNode> nodesSeen = new HashSet<>();
while (curr != null) {
if (nodesSeen.contains(curr)) {
return curr;
}
nodesSeen.add(curr);
curr = curr.next;
}
return curr;
}
}
Python 实现
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def detectCycle(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
curr = head
nodes_seen = set()
while curr:
if curr in nodes_seen:
return curr
nodes_seen.add(curr)
curr = curr.next
return curr
复杂度分析
- 时间复杂度:\(O(n)\)
- 空间复杂度:\(O(n)\)
解法二:双指针
思路
和 LeetCode 第 141 题一样,如果不想占用额外的空间的话,可以采用双指针的方式。
假设链表的起始节点为 A,环的入口节点为 B,两个指针(快慢指针)相交节点为 C,AB 两点之间的长度为 \(x\),BC 两点之间的长度为 \(y\),CB 两点之间的长度为 \(z\)。慢指针 slow 走过的长度为 \(x+y\),快指针 fast 为了“赶上”慢指针,应该走过的长度为 \(x + y + z + y\),同时,由于快指针的速度是慢指针的两倍,因此相同时间内,快指针走过的路程应该是慢指针(走过的路程)的两倍,即

\]
化简得,
\]
因此,如果此时有另外一个慢指针 slow2 从起始节点 A 出发,则两个慢指针会在节点 B (环的入口)相遇。
Java 实现
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode slow = head, fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
if (slow == fast) {
ListNode slow2 = head;
while (slow != slow2) {
slow = slow.next;
slow2 = slow2.next;
}
return slow;
}
}
return null;
}
}
// Runtime: 1 ms
// Your runtime beats 100.00 % of python submissions.
Python 实现
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def detectCycle(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
slow, fast = head, head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
if slow == fast:
slow2 = head
while slow != slow2:
slow = slow.next
slow2 = slow2.next
return slow
return None
# Runtime: 44 ms
# Your runtime beats 99.73 % of python submissions.
复杂度分析
- 时间复杂度:\(O(n)\),其中 \(n\) 表示链表的长度。最坏的情况下(链表有环),需要迭代的次数为 \(x + y + z = n\) 次,因此时间复杂度为 \(O(n)\)
- 空间复杂度:\(O(1)\),只需要存储 3 个引用
【LeetCode题解】142_环形链表2(Linked-List-Cycle-II)的更多相关文章
- Leetcode 141题 环形链表(Linked List Cycle) Java语言求解
题目描述: 给定一个链表,判断链表中是否有环. 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始). 如果 pos 是 -1,则在该链表中没有环. Map ...
- [LeetCode题解]142. 环形链表 II | 快慢指针
解题思路 本题是在141. 环形链表基础上的拓展,如果存在环,要找出环的入口. 如何判断是否存在环,我们知道通过快慢指针,如果相遇就表示有环.那么如何找到入口呢? 如下图所示的链表: 当 fast 与 ...
- LeetCode 141. 环形链表(Linked List Cycle)
题目描述 给定一个链表,判断链表中是否有环. 进阶:你能否不使用额外空间解决此题? 解题思路 快慢指针,慢指针一次走一步,快指针一次走两步,若两者相遇则说明有环,快指针无路可走则说明无环. 代码 /* ...
- [LeetCode题解]141. 环形链表 | 快慢指针
题目描述 给定一个链表,判断链表中是否有环. 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环. 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的 ...
- [LeetCode]题解(python):142-Linked List Cycle II
题目来源: https://leetcode.com/problems/linked-list-cycle-ii/ 题意分析: 给定一个链表,如果链表有环,返回环的起始位置,否则返回NULL.要求常量 ...
- 【链表】Linked List Cycle II
题目: Given a linked list, return the node where the cycle begins. If there is no cycle, return null. ...
- LeetCode 142. 环形链表 II(Linked List Cycle II)
142. 环形链表 II 142. Linked List Cycle II 题目描述 给定一个链表,返回链表开始入环的第一个节点.如果链表无环,则返回 null. 为了表示给定链表中的环,我们使用整 ...
- [LeetCode] Linked List Cycle II 单链表中的环之二
Given a linked list, return the node where the cycle begins. If there is no cycle, return null. Foll ...
- [LeetCode] 142. Linked List Cycle II 单链表中的环之二
Given a linked list, return the node where the cycle begins. If there is no cycle, return null. To r ...
- [算法][LeetCode]Linked List Cycle & Linked List Cycle II——单链表中的环
题目要求 Linked List Cycle Given a linked list, determine if it has a cycle in it. Follow up: Can you so ...
随机推荐
- Android-上下文菜单Menu
上一篇博客介绍了,Android-普通菜单Menu,而这篇博客介绍Android-上下文菜单Menu AndroidManifest.xml 中加入权限: <!-- 读取联系人数据的权限 --& ...
- 【算法34】蓄水池抽样算法 (Reservoir Sampling Algorithm)
蓄水池抽样算法简介 蓄水池抽样算法随机算法的一种,用来从 N 个样本中随机选择 K 个样本,其中 N 非常大(以至于 N 个样本不能同时放入内存)或者 N 是一个未知数.其时间复杂度为 O(N),包含 ...
- Mina的ssl加密
前面写的Mina的示例,都是可以通过telnet登录的,并且可以相互交互. 现在采用ssl加密的方式,对建立连接时,进行加密连接.这样,双方只有统一的加密,然后才可以连接. 密钥的生成之前有说过,里面 ...
- DBCC--CHECKDB--不可被替代的原因
CHECKSUM不能发现的两类问题 1. 发生在内存中的页错误,如内存损坏+第三方程序修改等 2. MS SQL Server潜在BUG导致的逻辑错误,该类错误可以使用重建索引或重建约束来修复 CHE ...
- asp.net 网站监控方案
前言:监控web网站方法有很多种,这篇文章说一下对windows服务器 asp.net网站的监控 采用的方案,Powershell + Influxdb + Grafana 1.PowerShell ...
- Easyui datagrid绑定数据,新增,修改,删除写法
@{ ViewBag.Title = "xw_xsfl"; } <script type="text/javascript"> var editIn ...
- 第六章 ReentrantLock源码解析2--释放锁unlock()
最常用的方式: int a = 12; //注意:通常情况下,这个会设置成一个类变量,比如说Segement中的段锁与copyOnWriteArrayList中的全局锁 final Reentrant ...
- AOP面向切面的基石——动态代理(一)
其实动态代理在Java里不是什么新技术了,早在java 1.2之后便通过 java.lang.reflect.InvocationHandler 加入了动态代理机制. 下面例子中,LancerEvol ...
- 修改tomcat7编码问题(重定向等)
修改tomcat默认编码格式: 修改tomcat下的conf/server.xml文件,找到如下代码: <Connector port="8080" protocol=&qu ...
- Ceres入门笔记
介绍 Ceres可以解决下列形式的边界约束鲁棒非线性最小二乘问题 (1) $\min\limits_{x}\quad \frac{1}{2} \sum\limits_{i}\rho_{i}\left( ...