【剑指offer】20. 链表中环的入口结点(java)

文章目录

  • 链表中环的入口结点
    • 描述
      • 输入描述:
      • 返回值描述:
    • 示例1
    • 示例2
    • 示例3
    • 思路
    • 完整代码

链表中环的入口结点

描述

给一个长度为n链表,若其中包含环,请找出该链表的环的入口结点,否则,返回null。

数据范围: n ≤ 10000 n≤10000 n10000 1 < = 结点值 < = 10000 1<=结点值<=10000 1<=结点值<=10000

要求:空间复杂度 O ( 1 ) O(1) O(1),时间复杂度 O ( n ) O(n) O(n)

例如,输入{1,2},{3,4,5}时,对应的环形链表如下图所示:

【剑指offer】20. 链表中环的入口结点(java)_第1张图片

可以看到环的入口结点的结点值为3,所以返回结点值为3的结点。

输入描述:

输入分为2段,第一段是入环前的链表部分,第二段是链表环的部分,后台会根据第二段是否为空将这两段组装成一个无环或者有环单链表

返回值描述:

返回链表的环的入口结点即可,我们后台程序会打印这个结点对应的结点值;若没有,则返回对应编程语言的空结点即可。

示例1

输入:

{1,2},{3,4,5}

返回值:

3

说明:

返回环形链表入口结点,我们后台程序会打印该环形链表入口结点对应的结点值,即3   

示例2

输入:

{1},{}

返回值:

"null"

说明:

没有环,返回对应编程语言的空结点,后台程序会打印"null"   

示例3

输入:

{},{2}

返回值:

2

说明:

环的部分只有一个结点,所以返回该环形链表入口结点,后台程序打印该结点对应的结点值,即2

思路

其实题目有一点没有说,那就是链表中各节点的值应该是不能有重复的,要不然这题应该是无解的

下面可以根据题目将链表分成一下几种情况:

  • 没有环,即输入第二段为空,此时直接返回null
  • 有环,此时从链表头部开始记录每个节点的值,然后一直循环遍历链表,当遇到重复元素值时就是找到了环的头部元素

这个用于记录数组元素的数据结构我选择ArrayList,因为其有个contains方法可以快速判断是否包含某个值

如果链表能循环为空,就说明其没有环,最后返回null

public ListNode EntryNodeOfLoop(ListNode pHead) {
    ArrayList<Integer> list = new ArrayList<Integer>();
    while (pHead != null) {
        if (list.contains(pHead.val)) {
            return pHead;
        }
        list.add(pHead.val);
        pHead = pHead.next;
    }
    return null;
}

其实用set记录也行,因为set不能包含重复元素,所以add时如果有重复元素会报错

然后看了别人的解法,发现有个快慢解法,过程非常巧妙,但需要花点时间去理解,感兴趣的可以自己去找一下这种解法

完整代码

import java.util.*;
/*
 public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}
*/
public class Solution {

    public ListNode EntryNodeOfLoop(ListNode pHead) {
        ArrayList<Integer> list = new ArrayList<Integer>();
        while (pHead != null) {
            if (list.contains(pHead.val)) {
                return pHead;
            }
            list.add(pHead.val);
            pHead = pHead.next;
        }
        return null;
    }
}

你可能感兴趣的:(剑指offer,链表,java,数据结构)