文章目录
用python 判断一个单链表是否有环.
https://leetcode.com/problems/linked-list-cycle/
思路1:
判断一个单链表是否有环,
可以用 set 存放每一个 节点, 这样每次 访问后把节点丢到这个集合里面.
其实 可以遍历这个单链表, 访问过后,
如果这个节点 不在 set 里面, 把这个节点放入到 set 集合里面.
如果这个节点在 set 里面 , 说明曾经访问过, 所以这个链表有重新 走到了这个节点, 因此一定有环
如果链表都走完了, 把所有的节点都放完了. 还是没有重复的节点, 那说明没有环.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
@Time : 2019/1/12 00:59
@File : has_circle.py
@Author : frank.chang@shoufuyou.com
https://leetcode.com/problems/linked-list-cycle/
141. Linked List Cycle
Easy
1231
93
Favorite
Share
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.
Example 1:
Input: head = [3,2,0,-4], pos = 1
Output: true
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: true
Explanation: There is a cycle in the linked list, where tail connects to the first node.
Example 3:
Input: head = [1], pos = -1
Output: false
Explanation: There is no cycle in the linked list.
Follow up:
Can you solve it using O(1) (i.e. constant) memory?
Accepted
340,579
Submissions
971,443
"""
class LinkNode:
def __init__(self, value):
self.value = value
self.next = None
class Solution1:
"""
思路分析:
判断一个单链表是否有环,
可以用 set 存放每一个 节点, 这样每次 访问后把节点丢到这个集合里面.
其实 可以遍历这个单链表, 访问过后,
如果这个节点 不在 set 里面, 把这个节点放入到 set 集合里面.
如果这个节点在 set 里面 , 说明曾经访问过, 所以这个链表有重新 走到了这个节点, 因此一定有环.
如果链表都走完了, 把所有的节点都放完了. 还是没有重复的节点, 那说明没有环.
"""
def hasCycle(self, head):
mapping = set()
flag = False
p = head
while p:
if p not in mapping:
mapping.add(p)
else:
flag = True
break
p = p.next
return flag
还有一个解决方案:
定义 两个指针, 一个快指针fast, 一个慢指针slow, 快指针一次走两步,慢指针一次走一步.
如果 两个指针相遇了, 则说明链表是有环的.
如果 fast 都走到null了, 还没有相遇则说明没有环.
为什么是这样呢? 简单分析一下?
用图形来分析一下,这样可以清晰一点.
因为快指针 先走 所以快指针先进入环,之后慢指针后进入环, 无论如何,
最后 要么 慢指针进入环的时候, 快指针可能已经走了 很多遍环, 也有可能没有走完环. 但无论如何 当慢指针 进入环的时候,
fast 有可能在 慢指针的后面, 或者前面, 无论如何 快指针 是必慢指针走的快的 , 所以 只要有环 一定可以 和慢指针来一次相遇.
你可能想 会不会错过呢?
答案 是不会的. 你想 快指针一次 走两步, 慢指针一次都一步.
假设 这是一条无穷尽的单链表. 他们 每走一步, 两者之间的距离就减1, 所以 只要链表足够长, 是一定会相遇的.
看下图:
class Solution:
"""
定义 两个指针, 一个快指针fast, 一个慢指针slow, 快指针一次都两步,慢指针一次走一步.
如果 两个指针相遇了, 则说明链表是有环的.
如果 fast 都走到null了, 还没有相遇则说明没有环.
"""
def hasCycle(self, head):
flag = False
if head is None or head.next is None or head.next.next is None:
return flag
fast = head.next.next
slow = head.next
while fast is not slow:
if fast.next is None or fast.next.next is None:
# no circle
return flag
fast = fast.next.next
slow = slow.next
# 相遇肯定有环
if fast is slow:
# hasCircle
flag = True
return flag
第二次做DAY20201130
闲下来 之前的代码 写的不够优雅,今天 重新修改了一下 之前的代码,这样写看起来 比 之前的代码 稍微 好看一点,详细请看下面
141. 环形链表
给定一个链表,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next
指针再次到达,则链表中存在环。 为了表示给定链表中的环,我们使用整数 pos
来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos
是 -1
,则在该链表中没有环。注意:pos
不作为参数进行传递,仅仅是为了标识链表的实际情况。
如果链表中存在环,则返回 true
。 否则,返回 false
。
进阶:
你能用 O(1)(即,常量)内存解决此问题吗?
示例 1:
输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。
示例 2:
输入:head = [1,2], pos = 0
输出:true
解释:链表中有一个环,其尾部连接到第一个节点。
示例 3:
输入:head = [1], pos = -1
输出:false
解释:链表中没有环。
提示:
- 链表中节点的数目范围是
[0, 104]
-105 <= Node.val <= 105
pos
为-1
或者链表中的一个 有效索引 。
方法1 路径记录法
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def hasCycle(self, head: ListNode) -> bool:
visited = set()
while head:
cur = head
if cur not in visited:
visited.add(cur)
else:
return True
head = head.next
return False
class Solution02:
def hasCycle(self, head: ListNode) -> bool:
seen = set()
while head:
if head in seen:
return True
seen.add(head)
head = head.next
return False
方法2 快慢指针法
第1种解法
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def hasCycle(self, head: ListNode) -> bool:
if not head:
return False
slow = head
fast = head.next
while fast and fast.next:
if fast ==slow:
return True
fast= fast.next.next
slow = slow.next
return False
另一种写法
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def hasCycle(self, head: ListNode) -> bool:
if head is None or head.next is None:
return False
slow = head
fast =head.next
while slow != fast:
if fast is None or fast.next is None:
return False
fast = fast.next.next
slow = slow.next
return True