Java同学的面试算法学习 7

49 阅读2分钟

链表中环的入口结点

题目描述

image-20240106202028127

示例

image-20240106202107927

思路

从题目和示例可知,这道题需要先判断链表是否存在环,然后再去寻找环的入口节点,判断是否存在环已经在之前的题目中写过,

这里主要分享如何找到环的入口节点, 其实就是使用一个整型数组来进行标记,指针不断移动遍历,用节点的值来作为数组的下标,访问过的标记为1(整型数组的元素的默认初始值为0),每次访问元素并通过数组判断对应节点是否被访问过,第一个被二次访问的节点就是环的入口

代码

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

    ListNode(int val) {
        this.val = val;
    }
}
*/
public class Solution {
    private boolean HaveLoop(ListNode root) {
        ListNode quick = root;
        ListNode slow = root;
        while (quick != null && quick.next != null) {
            quick = quick.next.next;
            slow = slow.next;
            if (quick == slow) {
                return true;
            }
        }
        return false;
    }
    public ListNode EntryNodeOfLoop(ListNode pHead) {
        //判断是否有环
        if (!HaveLoop(pHead)) {
            return null;
        }
        int[] arr = new int[10005];
        while (arr[pHead.val] == 0) {
            arr[pHead.val] = 1;
            pHead = pHead.next;
        }
        return pHead;
    }

}

官方解答

image-20240106205312884

image-20240106205330758

官方解答果然牛!

代码

public class Solution {
    //判断有没有环,返回相遇的地方
    public ListNode hasCycle(ListNode head) {
        //先判断链表为空的情况
        if(head == null) 
            return null;
        //快慢双指针
        ListNode fast = head; 
        ListNode slow = head;
        //如果没环快指针会先到链表尾
        while(fast != null && fast.next != null){ 
            //快指针移动两步
            fast = fast.next.next; 
            //慢指针移动一步
            slow = slow.next; 
            //相遇则有环,返回相遇的位置
            if(fast == slow) 
                return slow;
        }
        //到末尾说明没有环,返回null
        return null; 
    }
    
    public ListNode EntryNodeOfLoop(ListNode pHead) {
        ListNode slow = hasCycle(pHead);
        //没有环
        if(slow == null) 
            return null;
        //快指针回到表头
        ListNode fast = pHead; 
        //再次相遇即是环入口
        while(fast != slow){ 
            fast = fast.next;
            slow = slow.next;
        }
        return slow;
    }
}

总结

  1. 终于不看题解能够自己独立过题了:smile:,但是这道题也有对应的案例缺陷(如果环里面有个结点的值与入口的值一样,这段程序就过不了,尝试了一下居然过了),还是官方解答比较牛批。
  2. java数组的创建需要指定数组的大小来进行初始化,java数组的元素有初始化值,整形数组的元素初始化值为0,boolean类型的数组初始化值为false,String类型的元素初始化值为null;