链表学习二

链表学习二

链表中环的问题

判断是否有环

  1. 遍历链表加入hash,发生碰撞则说明有环;
  2. 使用快慢指针,如果相遇则说明有环;(有环一定会相遇,无环快的指针先到末尾)

确定环的入口

  1. 同上述方法一,第一次发生碰撞的节点即为环的入口;
public static ListNode detectCycleByMap(ListNode head) {
        ListNode pos = head;
        Set<ListNode> visited = new HashSet<ListNode>();
        while (pos != null) {
            if (visited.contains(pos)) {
                return pos;
            } else {
                visited.add(pos);
            }
            pos = pos.next;
        }
        return null;
    }
  1. 快慢指针法。

结论:找到第一次相遇的位置,之后一个指针在入口出发,另一个在相遇点以同速率出发,再次相遇时为环的入口。

在这里插入图片描述

由题意可知慢指针在环里移动不会超过一圈,假设慢指针走了a+b距离,则快指针走了a+n(b+c)+b的距离(n为快指针走的圈数),有a+n(b+c)+b=2(a+b),得出a=c+(n-1)(b+c),n为1时,说明a=c,则第一次相遇的位置,之后一个指针在入口出发,另一个在相遇点以同速率出发,再次相遇时为环的入口是正确的;n为2,3,4…时,说明一个指针在a上移动时,另一个指针转了(n-1)圈后又走了c的距离,恰好等于a,即在环的入口相遇。

    public static ListNode detectCycleByTwoPoint(ListNode head) {
        if (head == null) {
            return null;
        }
        ListNode slow = head, fast = head;
        while (fast != null) {
            slow = slow.next;
            if (fast.next != null) {
                fast = fast.next.next;
            } else {
                return null;
            }
            if (fast == slow) {
                ListNode ptr = head;
                while (ptr != slow) {
                    ptr = ptr.next;
                    slow = slow.next;
                }
                return ptr;
            }
        }
        return null;
    }
  1. 三次双指针方法

在知道环的长度和环的尾结点时,就能够通过倒数第K个元素的方法找到环的入口了。

第一次:通过快慢指针是否相遇来判断是否存在环;

第二次:在两个指针相遇点,一个指针不动,另一个指针继续走直到再次相遇能够得到环的长度L;

第三次:从起点开始,fast指针先走L,之后两指针以共同速率走,直到两指针再次相遇即为入口。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值