【LeetCode】142. Linked List Cycle II 解题报告(Python & C++)
作者: 负雪明烛
id: fuxuemingzhu
个人博客: http://fuxuemingzhu.cn/
题目地址:https://leetcode.com/problems/linked-list-cycle-ii/description/
题目描述
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.
Example 1:
Input: head = [3,2,0,-4], pos = 1
Output: tail connects to node index 1
Explanation: There is a cycle in the linked list, where tail connects to the second node.
Example 2:
Input: head = [1,2], pos = 0
Output: tail connects to node index 0
Explanation: There is a cycle in the linked list, where tail connects to the first node.
Example 3:
Input: head = [1], pos = -1
Output: no cycle
Explanation: There is no cycle in the linked list.
Follow up:
- Can you solve it without using extra space?
题目大意
找出单链表是否有环,如果有环返回环的入口,否则返回None.
解题方法
双指针
做过之前判断一个单链表中是否有环的题,我们知道可以通过一个指针走两步,一个指针走一步的方式,看两者是否相遇即可。这个题是之前的拓展。
如图所示,两个指针同时从直线起点开始,这个圈是顺时针方向走的,即走的顺序是S-O-x-c-O-x。
感谢评论区指正,如果SO线段的长度a足够长,而圈很小的时候,当两者相遇时,快指针多走的可能不止一圈。下面要证明如果相遇之后,慢指针回到原点继续走再相遇的点在O点。
首先要证明的是,两指针相遇时,慢指针还没有走完整个链表。
- 当慢指针没走完一圈时,显然成立
- 假设慢指针走完了一圈之后相遇,可以假定快指针在O的前一个位置,慢指针走一圈回到了O点,此时快指针走了两圈又回到了O的前一个位置,所以在慢指针走玩一圈之前就已经相遇。
快慢指针在x处第一次汇合,xo之间距离为x,假如快指针走了n圈,快指针走过的路程为a+x+n*(c + x),慢指针走过的路程为a+x,所以a+x+n*(c + x) = 2(a+x),所以a + x = n*(c + x),也就是SOx之间的距离等于n圈的长度,所以令慢指针从起点开始一次一步,快指针从x开始顺时针方向转也一次一步,同时前进,则慢指针走a时,快指针走了n*(c+x) - x的长度,则必会在O处相遇!
同时注意题目中说了,有可能不存在环,所以要进行判断。
二刷的时候提交错误了几次,原因在于判断fast == slow的时候写错位置了。应该写在移动指针之后,而不是在while循环刚开始的时候就判断。因为刚开始就判断的话,那么底下移动之后,可能直接就退出while了,没有做是否相等的判断。
# 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:
fast = fast.next.next
slow = slow.next
if fast == slow:
break
if not fast or not fast.next:
return None
slow = head
while slow != fast:
slow = slow.next
fast = fast.next
return fast
C++代码如下:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
if (!head) return nullptr;
ListNode* fast = head;
ListNode* slow = head;
while (fast && fast->next) {
fast = fast->next->next;
slow = slow->next;
if (slow == fast)
break;
}
if (!fast || !fast->next || slow != fast) return nullptr;
slow = head;
while (slow != fast) {
slow = slow->next;
fast = fast->next;
}
return fast;
}
};
set
其实也可以简单一点,如果我们保存走过的每个位置不就好了吗?所以,对于Python来说,可以直接把对象放到set中去,这样,当我们再次遍历到已经访问过的节点时,说明有了环,直接返回该节点即可。
# 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
"""
if not head: return None
visited = set()
while head:
if head in visited:
return head
visited.add(head)
head = head.next
return None
对于C++来说,有set和unordered_set两种集合,这里使用unordered_set,里面存放的内容是指向节点的指针,放指针一是可以成功存放,第二是如果已经遍历过了某个节点就相当于遍历过了这个指针。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
if (!head) return nullptr;
unordered_set<ListNode*> visited;
while (head) {
if (visited.count(head))
return head;
visited.insert(head);
head = head->next;
}
return nullptr;
}
};
参考资料:
http://blog.csdn.net/monkeyduck/article/details/50439840
https://blog.csdn.net/l294265421/article/details/50478818
日期
2018 年 3 月 12 日
2019 年 1 月 11 日 —— 小光棍节?
【LeetCode】142. Linked List Cycle II 解题报告(Python & C++)的更多相关文章
- 【算法分析】如何理解快慢指针?判断linked list中是否有环、找到环的起始节点位置。以Leetcode 141. Linked List Cycle, 142. Linked List Cycle II 为例Python实现
引入 快慢指针经常用于链表(linked list)中环(Cycle)相关的问题.LeetCode中对应题目分别是: 141. Linked List Cycle 判断linked list中是否有环 ...
- LeetCode: Linked List Cycle II 解题报告
Linked List Cycle II Given a linked list, return the node where the cycle begins. If there is no cyc ...
- Java for LeetCode 142 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 链表中的环 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 142. Linked List Cycle II 判断环入口的位置 C++/Java
Given a linked list, return the node where the cycle begins. If there is no cycle, return null. To r ...
- (链表 双指针) 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 142. Linked List Cycle II
Given a linked list, return the node where the cycle begins. If there is no cycle, return null. Note ...
- leetcode 142. Linked List Cycle II ----- java
Given a linked list, return the node where the cycle begins. If there is no cycle, return null. Note ...
随机推荐
- Python基础之流程控制if判断
目录 1. 语法 1.1 if语句 1.2 if...else 1.3 if...elif...else 2. if的嵌套 3. if...else语句的练习 1. 语法 1.1 if语句 最简单的i ...
- Linux-centos7设置静态IP地址
参考:https://blog.csdn.net/sjhuangx/article/details/79618865
- Identity Server 4 从入门到落地(七)—— 控制台客户端
前面的部分: Identity Server 4 从入门到落地(一)-- 从IdentityServer4.Admin开始 Identity Server 4 从入门到落地(二)-- 理解授权码模式 ...
- adverb
An adverb is a word or an expression that modifies a verb, adjective, another adverb, determiner [限定 ...
- 实时数仓(二):DWD层-数据处理
目录 实时数仓(二):DWD层-数据处理 1.数据源 2.用户行为日志 2.1开发环境搭建 1)包结构 2)pom.xml 3)MykafkaUtil.java 4)log4j.properties ...
- Linux 设置时区
一.查看和修改Linux的时区 1. 查看当前时区命令 : "date -R" 2. 修改设置Linux服务器时区方法 A命令 : "tzselect" 方法 ...
- Linux基础命令---mail邮件管理程序
mail mail是一个邮件的管理程序,可以用来发送或者接收邮件. 此命令的适用范围:RedHat.RHEL.Ubuntu.CentOS.Fedora. 1.语法 mail [选项] ...
- Siebel调用WebService
Siebel可以调用外部系统的接口,通过WebService的接入方式实现,所在的项目都是通过ESB,其他系统的接口都要经过ESB,由ESB提供WSDL文档,通过Siebel调用. 一.修改Tools ...
- 数据库ER图基础概念
ER图分为实体.属性.关系三个核心部分.实体是长方形体现,而属性则是椭圆形,关系为菱形. ER图的实体(entity)即数据模型中的数据对象,例如人.学生.音乐都可以作为一个数据对象,用长方体来表示, ...
- OpenStack之之一: 快速添加计算节点
根据需求创建脚本,可以快速添加节点#:初始化node节点 [root@node2 ~]# systemctl disable NetworkManager [root@node2 ~]# vim /e ...