黄金-链表中的环问题

1.链表中环的问题

1.1.判断是否有环

可以用hash或者set来做,思路比较简单。

空间复杂度为O(1):使用快慢双指针,若有环,则两指针必定会相遇

 public boolean hasCycle(ListNode head) {
        //利用set的不可重复解决,将遍历过的节点存入set,若不能存入,则说回到了已经遍历过的节点上,有环
        //Set<ListNode> set=new HashSet<ListNode>();
        // while(head!=null){
        //     if(!set.add(head)){
        //         return true;
        //     }
        //     head=head.next;
        // }
        // return false;
        if(head == null || head.next == null) return false;
        ListNode fast = head;
        ListNode slow = head;
        while(fast != null && fast.next != null){
            fast = fast.next.next;
            slow = slow.next;
            if(slow == fast) return true;
        }
        return false;
    }
1.2.判断是否有环,并返回环的入口

结论:还是快慢双指针,我们需要制造两次相遇,在第一次相遇后,fast指向头节点,slow指向第一次相遇出,两者以相同速度前进,相遇时,此处就是环的入口。

为什么?

在Z处相遇,

步数:fast = a+b+c+b; slow = a+b;

fast步数是slow的两倍,所以2*(a+b) = a+b+c+b。可以得到a=c。

也就是说,在第一次相遇后,fast指向头节点,slow指向第一次相遇出,两者以相同速度前进,相遇时,此处就是环的入口。

多圈后相遇也是一样的,区别是a对于c多加了n圈的长度(a=c+(n-1)len)

public ListNode detectCycle(ListNode head) {
        ListNode fast = head,slow = head;
        // 构建第一次相遇(fast 2步,slow 1步)
        while(true){
            // 没有环
            if(fast == null || fast.next == null) return null;
            fast = fast.next.next;
            slow = slow.next;
            if(slow == fast) break;
        }
        // 构建第二次相遇,相遇处就是环的入口
        fast = head;
        while(fast != slow){
            fast = fast.next;
            slow = slow.next;
        }
        return fast;
    }
   slow = slow.next;
    }
    return fast;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值