leetcode-142:环形链表 II

简介: leetcode-142:环形链表 II

题目

题目链接

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

为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意,pos 仅仅是用于标识环的情况,并不会作为参数传递到函数中。

示例 1:

输入:head = [3,2,0,-4], pos = 1
输出:返回索引为 1 的链表节点
解释:链表中有一个环,其尾部连接到第二个节点。

示例 2:

输入:head = [1,2], pos = 0
输出:返回索引为 0 的链表节点
解释:链表中有一个环,其尾部连接到第一个节点。

示例 3:

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

解题

方法一:哈希表

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
class Solution:
    def detectCycle(self, head: ListNode) -> ListNode:
        hush = {}
        cur = head
        while cur:
            if cur in hush:
                return cur
            hush[cur]=1
            cur = cur.next
        return None

方法二:双指针(进阶:空间复杂度O(1))

此方法详细链接

首先是环内相遇

后续可以推导出z=x,让一个指针从头节点开始,另一个指针一个从第一次环内相遇开始,它们接下来第一次相遇就是环形入口节点。(具体推导见详细链接)

class Solution(object):
    def detectCycle(self, head):
        fast, slow = head, head
        while True:
            if not (fast and fast.next): return
            fast, slow = fast.next.next, slow.next
            if fast == slow: break # 这行在后面,不然开始就head==head,直接break了
        fast = head
        while fast != slow:
            fast, slow = fast.next, slow.next
        return fast

由于开始都是head,后面的循环的写法要稍微变化一下(与环形链表1有所区别)

这种写法,只能开始都是head,这样才能保证两倍关系,由于fast一开始和slow相同,所以就不能使用while fast!=slow的写法了.




如果非要类似于环形链表 1的这种写法,slow=head,fast=head.next

那么slow走的步长的2倍还要+1

image.png


也就是说当n=1(fast绕了1圈),此时x=z+1

下面就需要p1=fast.next

python解法

class ListNode:
    def __init__(self, x):
        self.val = x
        self.next = None
class Solution:
    def detectCycle(self, head: ListNode) -> ListNode:
        if not head:
            return 
        slow = head
        fast = head.next
        p1=None
        while fast and fast.next:
            if slow==fast:
                p1 = fast.next  #这一步是关键
                break
            else:
                slow = slow.next
                fast = fast.next.next
        if not p1:
            return 
        p2 = head
        while p1!=p2:
            p1=p1.next
            p2=p2.next
        return  p1

c++解法

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        if(!head){
            return nullptr;
        }
        ListNode* slow=head;
        ListNode* fast=head;
        while(true){
            if(!(fast->next&&fast->next->next)){
                return nullptr;
            }
            slow = slow->next;
            fast = fast->next->next;
            if(slow==fast){
                break;
            }
        }
        fast=head;
        while(slow!=fast){
            slow=slow->next;
            fast=fast->next;
        }
        return slow;
    }
};

java解法

public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode slow=head,fast=head;
        while(true){
            if(fast==null||fast.next==null) return null;
            slow=slow.next;
            fast=fast.next.next;
            if(slow==fast) break;
        }
        fast=head;
        while(slow!=fast){
            slow=slow.next;
            fast=fast.next;
        }
        return slow;
    }
}
相关文章
|
2月前
【力扣】-- 移除链表元素
【力扣】-- 移除链表元素
37 1
|
2月前
Leetcode第21题(合并两个有序链表)
这篇文章介绍了如何使用非递归和递归方法解决LeetCode第21题,即合并两个有序链表的问题。
51 0
Leetcode第21题(合并两个有序链表)
|
2月前
LeetCode第二十四题(两两交换链表中的节点)
这篇文章介绍了LeetCode第24题的解法,即如何通过使用三个指针(preNode, curNode, curNextNode)来两两交换链表中的节点,并提供了详细的代码实现。
22 0
LeetCode第二十四题(两两交换链表中的节点)
|
2月前
Leetcode第十九题(删除链表的倒数第N个节点)
LeetCode第19题要求删除链表的倒数第N个节点,可以通过快慢指针法在一次遍历中实现。
44 0
Leetcode第十九题(删除链表的倒数第N个节点)
|
2月前
|
索引
力扣(LeetCode)数据结构练习题(3)------链表
力扣(LeetCode)数据结构练习题(3)------链表
90 0
|
2月前
【LeetCode 10】142. 环形链表 II
【LeetCode 10】142. 环形链表 II
22 0
|
2月前
【LeetCode 09】19 删除链表的倒数第 N 个结点
【LeetCode 09】19 删除链表的倒数第 N 个结点
17 0
|
2月前
【LeetCode 08】206 反转链表
【LeetCode 08】206 反转链表
13 0
|
2月前
【LeetCode 06】203.移除链表元素
【LeetCode 06】203.移除链表元素
32 0
|
2月前
【数据结构】环形、相交、回文、分割、合并、反转链表
【数据结构】环形、相交、回文、分割、合并、反转链表
29 0