142.环形链表II

快慢指针方法

public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode slow = head;
        ListNode fast = head;
        while (fast != null && fast.next != null) {
            slow=slow.next;
            fast=fast.next.next;
            if(slow==fast){
                //两指针相遇
                ListNode index1=head;
                ListNode index2=slow;
                while(index1!=index2){
                    index1=index1.next;
                    index2=index2.next;
                }
                return index1;
            }
        }
        // 环形链表不可能有null;
        return null;
    }
}

需要解决的问题

  • 判断链表是否有环
  • 如果链表有环,如何找到环的入口

解决方法

  • 设定快慢指针slow和fast,slow每次走一步,fast每次走两步,如果链表有环,slow和fast一定能在环中相遇。因为slow和fast的相对来说是slow原地不动,fast每次向前走一步,所以fast一定能在环中追上slow。
  • 假设链表中有环,设head到环的入口节点数为x,入口到相遇点的节点数为y,相遇点到入口的节点数为z。那么当slow和fast相遇时slow走过的节点数为x+y,fast走过的节点数为x+n(y+z),并且fast走过的节点数是slow的两倍。所以有x=(n-1)(y+z)+z,意味着从head出发一个index1,从相遇点出发一个index2,当index1和index2相遇时,他们指向的节点就是环的入口。
  • 其中有一个疑惑的点在于slow和fast相遇的时候,为什么slow走过的节点数是x+y,而不是slow也在环里转了几圈。假设slow进入环的那一刻就原地不动,那么fast每次向前走一步,fast肯定不用一圈的时间就可以追上slow,所以slow和fast在slow进入环之后不到一圈的时间就会相遇。

哈希数组方法

public class Solution {
    public ListNode detectCycle(ListNode head) {
        Set<ListNode> set = new HashSet<>();
        ListNode cur=head;
        while(cur!=null){
            if(!set.add(cur)){
                //说明这个节点已经被放入了set
                return cur;
            }
            cur=cur.next;
        }
        return null;
    }
}
  • 9
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值