[快慢指针]141 - 环链表 - python + Java

99 阅读2分钟

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

示例 1:


在这里插入图片描述

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

示例 2:


在这里插入图片描述

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

示例 3:


在这里插入图片描述

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

进阶:你能用 O(1)(即,常量)内存解决此问题吗?


题目要求判断链表是否存在环,该问题可以理解为链表尾节点的next指向的元素是None还是前面已经访问过的某一元素。因此,一种做法可以使用额外的数组r存储已经访问过的元素,然后依次遍历链表中的元素

  • 如果当前节点的next指向的元素并没有在r中出现,则指针往后继续
  • 否则返回True,表示链表中存在环
class Solution:
    def hasCycle(self, head: ListNode) -> bool:
        if not head: return False

        r = []
        while head:
            if head in r:
                return True
            r.append(head)
            head = head.next
        
        return False

解决链表问题除了上述的这种暴力的方法外,还有一种常用的方法便是双指针法,即快慢指针。设置慢指针slow和快指针quick初始都指向链表头部,然后它们均往后走。slow每次走一步,quick每次走两步

  • 如果链表中存在环,两者在未来的某个时刻一定会相遇

  • 如果quick某时刻的next指向None,则链表中必定无环


    在这里插入图片描述

# 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 or not head.next: return False

        slow, fast = head, head
        while fast and fast.next:
            slow, fast = slow.next, fast.next.next
            if slow == fast:
                return True

        return False

Java解题代码如下:

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public boolean hasCycle(ListNode head) {
        if(head == null || head.next == null){
            return false;
        }

        ListNode slow = head;
        ListNode fast = head;
        while(fast != null && fast.next != null){
            slow = slow.next;
            fast = fast.next.next;
            if(slow == fast){
               return true;
            }
        }

        return false;
    }
}