java算法系列,第十三篇:弗洛伊德龟兔算法----判断一个链表是否有回环

在计算机科学中,一个链表可以被描述为一系列节点,每个节点包含数据和指向下一个节点的引用。当一个链表中的某个节点的引用指向之前的某个节点,就会形成一个回环。换句话说,链表的末尾节点连接到了链表中的某个前面节点,导致链表成环。

弗洛伊德龟兔算法(Floyd's Tortoise and Hare Algorithm)是一种用于检测链表是否存在回环的快速方法。它基于两个指针,一个称为“龟”(tortoise)指针,另一个称为“兔”(hare)指针。算法的核心思想是,如果链表中存在回环,那么龟兔指针最终会在某一点相遇。

具体算法步骤如下:

  1. 初始化龟兔指针,都指向链表的头节点。
  2. 在每一步迭代中,龟指针向前移动一步,兔指针向前移动两步。
  3. 如果链表存在回环,那么龟兔指针最终会在某一点相遇,此时即可判断链表中存在回环。

这是因为,当龟兔指针进入回环部分后,它们的相对速度就像是在一个环形跑道上,兔指针的速度是龟指针的两倍。因此,兔指针会逐渐靠近龟指针,最终相遇在某个节点上。

弗洛伊德龟兔算法的时间复杂度为O(n),其中n是链表的节点数。由于算法仅使用了常数级的额外空间,因此它在判断链表中是否存在回环时非常高效。

在下一部分,我们将深入探讨如何在Java中实现弗洛伊德龟兔算法。

@Test
    @DisplayName("弗洛伊德龟兔算法")
    public void test30()
    {
        ListNode node8 = new ListNode(8,null);
        ListNode node7 = new ListNode(7,node8);
        ListNode node6 = new ListNode(6,node7);
        ListNode node5 = new ListNode(5,node6);
        ListNode node4 = new ListNode(4,node5);
        ListNode node3 = new ListNode(3,node4);
        ListNode node2 = new ListNode(2,node3);
        ListNode node1 = new ListNode(1,node2);
        node8.setNext(node4);
        Integer i = isCircular(node1);
        if (i != null)
        {
            System.out.println(true);
            System.out.println(i);
        }
        else
        {
            System.out.println(false);
        }


    }
    /**
     * 判断是否有环
     * @param  head  链表头节点
     * @return 如果链表中有回环就返回环入口的值,如果没有就返回null
     * */
    public Integer isCircular(ListNode head)
    {
        Integer i = null;
        ListNode r = head;
        ListNode t = head;
        while (r != null && r.getNext() !=null)
        {
            r = r.getNext().getNext();
            t = t.getNext();
            if (r == t)//如果相遇了,就表明有环入口
            {
                r = head;
                if (r != t)//如果尾节点不指向头节点,换句话说头节点不是入口节点
                {
                    while (r != t)//让兔子扮演乌龟,这次他们都一次走一步,直到相遇
                    {
                        r = r.getNext();
                        t = t.getNext();
                    }
                }
                i = t.getVal();//相遇位置就是环入口
                return i;
            }
        }
        return i;//不存在回环的情况下直接返回null
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值