阿里云高频编程考题:环形链表(简单)

题目描述

给你一个链表的头节点 head ,判断链表中是否有环。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。

如果链表中存在环 ,则返回 true 。 否则,返回 false 。

示例 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 或者链表中的一个 有效索引 。

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

解题思路

判断链表中是否有环,可以使用一种高效的算法,即 Floyd 的兔子和乌龟算法(也叫做 快慢指针算法),可以在 O(n) 时间复杂度和 O(1) 空间复杂度下解决问题:

  1. 使用快慢指针:

    初始化两个指针,slowfastslow 每次移动一个节点,fast 每次移动两个节点;如果链表中存在环,那么 slowfast 会在环中相遇;如果链表中没有环,fast 指针会到达链表末尾(即 fastfast.next 变为 null)。
  2. 过程:

    初始化 slowfast 指针都指向链表的头节点;遍历链表,移动指针:fast 移动到下两个节点。slow 移动到下一个节点。如果 slowfast 指针在某一时刻相遇,链表中存在环。如果 fast 指针到达链表的末尾,链表中没有环。

复杂度分析

  • 时间复杂度: O(n)。每个节点最多访问两次,分别是快指针和慢指针的访问。
  • 空间复杂度: O(1)。只使用了常量级别的额外空间(两个指针)。

代码实现

package org.zyf.javabasic.letcode.hot100.list;

import org.zyf.javabasic.letcode.list.base.ListNode;

/**
 * @program: zyfboot-javabasic
 * @description: 环形链表​
 * @author: zhangyanfeng
 * @create: 2024-08-22 00:12
 **/
public class HasCycleSolution {
    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; // 快指针到达链表末尾,说明链表没有环
    }

    public static void main(String[] args) {
        HasCycleSolution solution = new HasCycleSolution();

        // 测试用例 1: 有环的链表
        ListNode head1 = new ListNode(3);
        head1.next = new ListNode(2);
        head1.next.next = new ListNode(0);
        head1.next.next.next = new ListNode(-4);
        head1.next.next.next.next = head1.next; // 尾部连接到第二个节点
        System.out.println("Test Case 1: " + solution.hasCycle(head1)); // 应该输出 true

        // 测试用例 2: 有环的链表
        ListNode head2 = new ListNode(1);
        head2.next = new ListNode(2);
        head2.next.next = head2; // 尾部连接到第一个节点
        System.out.println("Test Case 2: " + solution.hasCycle(head2)); // 应该输出 true

        // 测试用例 3: 无环的链表
        ListNode head3 = new ListNode(1);
        System.out.println("Test Case 3: " + solution.hasCycle(head3)); // 应该输出 false
    }
}

具体可参考:https://zyfcodes.blog.csdn.net/article/details/141401712

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值