给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null

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

说明:不允许修改给定的链表。

Given a linked list, return the node where the cycle begins. If there is no cycle, return null.

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.

Note: Do not modify the linked list.

示例 1:

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

示例 2:

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

示例 3:

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

进阶: 你是否可以不用额外空间解决此题?

Follow-up: Can you solve it without using extra space?

解题思路:

和上一道题比只多了一步判断入环节点在哪。两种方法:

哈希表:

哈希表添加节点时只要发现节点已经存在了,证明就有环形链表。并且已存在的节点即为入环节点

双指针:

画了个图帮助理解:

一快一慢双指针开始从头结点遍历链表,快节点速度为2,慢节点速度为1:

相遇时:

慢节点走了:a+b

由于快指针速度是慢指针的2倍,快节点走了:2(a+b)

快慢节点相遇时快节点比慢节点刚好多走了一圈环形节点。快节点走了:(a+b)+(b+c)

列方程:2(a+b)=(a+b)+(b+c)

解得 a=c

也就是说:相遇节点到入环节点的长度和头节点到入环节点的长度相等

可以得出结论,如果此时让慢节点或快节点中的一个指向头节点,另一个留在相遇节点,然后速度都为1,继续遍历链表,双指针再次相遇时的节点刚好是入环节点。

注:为了理解方便,把长度 b 定为上半部分长度,实际上 b 应该为快慢节点相遇时慢节点绕过环形链表的总长度

哈希表解题:

Java:

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

Python:

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

双指针解题:

Java:

public class Solution {
public ListNode detectCycle(ListNode head) {
if (head == null || head.next == null) {
return null;
}
ListNode slow = head;
ListNode fast = head;
while (fast != null && fast.next != null) {//快指针及其下一位是否为null
slow = slow.next;
fast = fast.next.next;
if (slow == fast) {//如果相同,存在环形链表
slow = head;//指向头节点
while (slow != fast) {//继续遍历,再次相遇时的节点即为入环节点
slow = slow.next;
fast = fast.next;
}
return slow;
}
}
return null;
}
}

Python:

class Solution(object):
def detectCycle(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
if head is None or head.next is None:
return None
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:
slow = head
while slow != fast:
slow = slow.next
fast = fast.next
return slow
return None

欢迎关注公众号:爱写Bug(ID:iCodeBugs)

最新文章

  1. AVLTree 平衡树
  2. IT软件开发常用英语词汇
  3. 自定义右键菜单中bug记录
  4. phpDocumentor 注释语法详解
  5. 最终排名 sdut 2446
  6. VirtualBox的四种网络连接方式
  7. jsp页面间传递参数 中文乱码问题(zz)
  8. 第二sprint总结
  9. opencv linux
  10. [置顶] Ajax核心--XMLHttpRequest对象
  11. Bootstrap验证控件的使用
  12. 《JS权威指南学习总结--1.1语言核心》
  13. 重新认识alias:通过alias让rm更安全
  14. 删除“自豪的采用wordpress”
  15. 一个逼格很低的appium自动化测试框架
  16. 按键精灵PC版&lt;末日王者&gt;
  17. iOS 自定义底部tabbar加号按钮实现方法
  18. Python中关于if __name__==&#39;__main__&#39;的问题
  19. Spark集群之yarn提交作业优化案例
  20. Java关键字final、static使用总结(转)

热门文章

  1. Unity BehaviorDesigner行为树基础总结
  2. 使用Redis实现最近N条数据的决策
  3. Netty—TCP的粘包和拆包问题
  4. [debug] 关闭vs的增量链接
  5. C#函数的参数传递2(ref\out)
  6. HTTP Error 500.0 - ANCM In-Process Handler Load Failure 排错历程
  7. Java的包
  8. 设置view的layer属性方法
  9. [PHP] time_wait与长连接短连接
  10. 渗透测试学习 十八、 XSS跨站脚本漏洞详解 续