数据结构使用快慢指针找出有环链表入口

当快慢指针相遇时,我们可以判断到链表中有环,这时重新设定一个新指针指向链表的起点,且步长与慢指针一样为1,则慢指针与“新”指针相遇的地方就是环的入口。证明这一结论牵涉到数论的知识,这里略,只讲实现。
在这里插入图片描述
在这里插入图片描述
这是一个哔哩哔哩老师错误的代码(bilibili里的2020JAVA基础-深入系统的学习数据结构与算法),我觉的逻辑是有一定的问题,会出现死循环。
什么情况呢?????
当有环链表出现足够长的没环的地方,此时就有可能出现死循环,当圆环节点数为3时,slow和fast相遇只需要3步,当前边足够长temp还没走到,他们又相遇了,temp又指向了first,所以这个逻辑肯定会出现死循环。错误代码如下。。。。。。
使用我的下边图像,使用上边的错误代码,老师的逻辑一定是错的(自己去画)


我画了一下正确代码的图像(根据我的代码逻辑)。

在这里插入图片描述

public class QuickSlowMid {
    //节点类
    private static class Node<T> {
        T item;
        Node next;
        public Node(T item, Node next) {
            this.item = item;
            this.next = next;
        }
    }

    public static void main(String[] args) {
        Node<String> one = new Node<>("a", null);
        Node<String> two = new Node<>("b", null);
        Node<String> three = new Node<>("c", null);
        Node<String> four = new Node<>("d", null);
        Node<String> five = new Node<>("e", null);
        Node<String> six = new Node<>("f", null);
        Node<String> seven = new Node<>("g", null);
        one.next = two;
        two.next = three;
        three.next = four;
        four.next = five;
        five.next = six;
        six.next = seven;
        seven.next = five;
        Node entrance = getEntrance(one);
        System.out.println(entrance.item);
    }

    public static Node getEntrance(Node node) {
        Node fast = node;
        Node slow = node;
        Node temp = null;
        while (fast != null && fast.next != null) {
            fast = fast.next.next;
            slow = slow.next;
            if (fast == slow) {
                temp = node;
                continue;
            }

            if (temp != null) {
                temp = temp.next;
                if (temp == slow) {
                    break;
                }

            }
        }

        return temp;
    }

正确的代码:
不满足这种状况(一个圆环)
满足所有有环情况。

public class QuickSlowMid {
    //节点类
    private static class Node<T> {
        T item;
        Node next;

        public Node(T item, Node next) {
            this.item = item;
            this.next = next;
        }
    }

    public static void main(String[] args) {
        Node<String> one = new Node<>("a", null);
        Node<String> two = new Node<>("b", null);
        Node<String> three = new Node<>("c", null);
        Node<String> four = new Node<>("d", null);
        Node<String> five = new Node<>("e", null);
        Node<String> six = new Node<>("f", null);
        Node<String> seven = new Node<>("g", null);
        one.next = two;
        two.next = three;
        three.next = four;
        four.next = five;
        five.next = six;
        six.next = seven;
        seven.next = seven;
        Node entrance = getEntrance(one);
        System.out.println(entrance.item);
    }

    public static Node getEntrance(Node node) {
        Node fast = node;
        Node slow = node;
        Node temp = null;
        while (fast != null && fast.next != null) {
            fast = fast.next.next;
            slow = slow.next;
            if (fast == slow) {
                temp = node;
                while (true){
                    temp=temp.next;
                    slow=slow.next;
                    if (slow==temp){
                        return temp;
                    }
                }
            }
        }
        return null;
    }


}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值