Leetcode-142 环形链表 II

题目

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

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

不允许修改 链表。

 

示例 1:

输入:head = [3,2,0,-4], pos = 1
输出:返回索引为 1 的链表节点
解释:链表中有一个环,其尾部连接到第二个节点。

示例 2:

 

 

输入:head = [1,2], pos = 0
输出:返回索引为 0 的链表节点
解释:链表中有一个环,其尾部连接到第一个节点。

示例 3:

 

 

输入:head = [1], pos = -1
输出:返回 null
解释:链表中没有环。

 

提示:

  • 链表中节点的数目范围在范围 [0, 104]
  • -105 <= Node.val <= 105
  • pos 的值为 -1 或者链表中的一个有效索引

 

进阶:你是否可以使用 O(1) 空间解决此题?

哈希表法

每个节点的地址都是唯一的,所以可以将节点地址加入HashSet中,等下一次发现相同元素则代表遇到环了。

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    //遍历环形链表,依次将节点放入set中,如果下次放入的节点已经在set中,说明这个节点就是入环节点
    public ListNode detectCycle(ListNode head) {
        Set<ListNode> nodeSet = new HashSet<ListNode>();

        while(head != null){
            if(nodeSet.contains(head)){
                return head;
            }
            else{
                nodeSet.add(head);
                head = head.next;
            }
        }

        return head;
    }
}

双指针法

设置快指针以2节点速度遍历,慢指针以1节点每秒遍历,当两个指针相遇时,慢指针走了n个环的长度。设链表开头到入环点的长度为a,链表环的长度为b,则慢指针再走a长度就到入环点。
/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    //双指针法,设置快指针以2节点速度遍历,慢指针以1节点每秒遍历,当两个指针相遇时,慢指针走了n个环的长度。设链表开头到入环点的长度为a,链表环的长度为b,则慢指针再走a长度就到入环点。
    public ListNode detectCycle(ListNode head) {
        ListNode fastNode = head;
        ListNode slowNode = head;

        while(fastNode != null){
            slowNode = slowNode.next;
            if(fastNode.next != null){
                fastNode = fastNode.next.next;
            }
            else{
                //如果fastNode.next为null,说明直接遍历完链表了,链表无环,返回null
                return null;
            }

            if(slowNode == fastNode){
                //两链表相遇时,慢指针走了nb的距离,让快指针从链表头开始和慢指针以一个节点速度遍历,两者再次相遇的节点就是链表入环点
                fastNode = head;
                while(fastNode != slowNode){
                    fastNode = fastNode.next;
                    slowNode = slowNode.next;
                }
                return slowNode;
            }
        }

        return null;
    }
}

学到和回忆了

  • 寻找距离尾部第K个节点、寻找环入口、寻找公共尾部入口等链表问题都可以用双指针法解决

参考

环形链表 II - 环形链表 II - 力扣(LeetCode) (leetcode-cn.com)

环形链表 II(双指针法,清晰图解) - 环形链表 II - 力扣(LeetCode) (leetcode-cn.com)

posted @ 2022-04-02 21:06  心空之上  阅读(14)  评论(0)    收藏  举报