142. 环形链表 II

题目描述:

给定一个链表的头节点  head ,返回链表开始入环的第一个节点。如果链表无环,则返回 null。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

不允许修改 链表。

LevelAC rate
Medium56.4%


题目解析(哈希表存储):

使用哈希表将我们经过的结点存储起来,直到出现了第一个重复结点时,则该结点为入环的第一个节点。代码如下:

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode detectCycle(ListNode head) {
        if(head==null)return null;
        HashMap<ListNode,Integer> map = new HashMap<ListNode,Integer>();
        while(head.next!=null){
            if(map.containsKey(head))return head;
            map.put(head,0);
            head = head.next;
        }
        return null;
    }
}

执行用时:3 ms, 在所有 Java 提交中击败了20.54%的用户

内存消耗:41.9 MB, 在所有 Java 提交中击败了45.28%的用户

题目解析(快慢指针):

快慢指针的原理就不介绍了,详细可以看:

第141题 环形链表 (qq.com)icon-default.png?t=M85Bhttps://mp.weixin.qq.com/s?__biz=Mzk0MjM5ODM2NQ==&mid=2247483668&idx=1&sn=db15fdb9c00ae84ea2d26980bb5172b6&chksm=c2c28fe6f5b506f0adf28dc94499214b405cccc9344003e7b3e5b67e58d8b7e07e24b911368c&scene=21#wechat_redirect

使用快慢指针,这里涉及到了数学计算的问题,比如从头结点到入环的第一个结点需要走A步,绕环一圈需要走B步,假设目前快慢指针于X处相遇,相遇位置距入环结点需要走X步,那么也就是说此时快指针走了A+BN+X步,此时慢指针走了A+X步,快指针所走的距离应该是慢指针的两倍,也就是A+BN+X=2A+2X,即X=BN-A。这时将快指针的速度设为1,将慢指针放到头结点速度不变,慢指针到入环处需要走A步,而快指针需要走B-X=A-B(N-1)步。所以二者会在入环处相,代码如下:


/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode detectCycle(ListNode head) {
        if(head==null)return null;
        ListNode slow = head;
        ListNode quick = head;
        while(quick.next!=null&&quick.next.next!=null){
            slow = slow.next;
            quick = quick.next.next;
            if(slow==quick){
                slow = head;
                while(slow!=quick){
                    slow = slow.next;
                    quick = quick.next;
                }
                return slow;
            }
        }
        return null;
    }
}

执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户

内存消耗:41.6 MB, 在所有 Java 提交中击败了80.87%的用户

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值