链表中环的入口结点
题目描述
示例
思路
从题目和示例可知,这道题需要先判断链表是否存在环,然后再去寻找环的入口节点,判断是否存在环已经在之前的题目中写过,
这里主要分享如何找到环的入口节点, 其实就是使用一个整型数组来进行标记,指针不断移动遍历,用节点的值来作为数组的下标,访问过的标记为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;
}
}
官方解答
官方解答果然牛!
代码
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;
}
}
总结
- 终于不看题解能够自己独立过题了:smile:,但是这道题也有对应的案例缺陷(如果环里面有个结点的值与入口的值一样,这段程序就过不了,尝试了一下居然过了),还是官方解答比较牛批。
- java数组的创建需要指定数组的大小来进行初始化,java数组的元素有初始化值,整形数组的元素初始化值为0,boolean类型的数组初始化值为false,String类型的元素初始化值为null;