链表--如何检测一个链表是否有环及如何找到环的入口点

思路:
设置一个快指针fast,一个慢指针slow,二者初始都指向链表头,fast一次走两步,slow一次走一步,两个指针同时向前移动,每移动一次,两个指针都要进行比较,如果快指针等于慢指针,则证明这是个有环的单链表,否则如果fast先行到达链表尾部或为NULL,则证明这是个不带环的单链表。
如何找到环的入口点

思路:
如果单链表有环,当slow指针和fast指针相遇时,slow指针还没有遍历完链表,而fast指针已经在环内循环n(n>=1)圈了,假设此时slow指针走了s步,fast指针走了2s步,r为fast在环内转了一圈的步数,a为从链表头到入口点的步数,b为从入口点到相遇点的步数,c为从相遇点再走c步到达入口点,L为整个链表的长度。

slow指针走的步数:
s = a + b
fast指针走的步数:
2s = s + nr 即:s = nr
链表的长度:
L = a + b + c = a+r
由上可得:
2*(a + b) =s + nr ​​​​​​
而 b= r - c,所以:
a + b = n
r
a = n r - b = nr - (r - c) = (n-1)*r - c
由上可得,所以:
a = (n -1)*r +c
综上可得:从链表头到环入口点等于(n - 1)循环内环 + 相遇点到环入口点,于是在链表头和环入口点分别设置一个指针,同时出发,每次各走一步,它们必定会相遇,且第一次相遇的点就是环入口点。

public static Node findLoopPort(Node head) {
        Node slow = head;
        Node fast = head;
        //先判断该链表是否有环
        while(fast != null && fast.next !=null) {
            fast = fast.next.next;
            slow = slow.next;
            if(fast == slow) {
                break;
            }
        }
        if(fast == null || fast.next == null) {
            return null;
        }
        //如果链表有环,则将slow设置指向链表头,此时fast指向相遇点,然后同时开始移动,直到两个指针相遇
        slow = head;
        while(slow != fast) {
            slow = slow.next;
            fast = fast.next;
        }
        return slow;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值