题目描述
给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
思路1
运用哈希表,循环链表的入口会首次插入两次,则遇到重复用Hashmap即可搞定。
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
*/
import java.util.HashMap;
public class Solution {
public ListNode EntryNodeOfLoop(ListNode pHead)
{
HashMap<ListNode,Integer> hash = new HashMap<>();
ListNode node = null;//node结点暂存环的入口结点
while(pHead != null){
if(hash.containsKey(pHead)){
node = pHead;
break;
}
else{
hash.put(pHead, 1);
}
pHead = pHead.next;
}
return node;
}
}
参考别人思路:
- 第一步,找环中相汇点。分别用p1,p2指向链表头部,p1每次走一步,p2每次走二步,直到p1==p2找到在环中的相汇点。
- 第二步,找环的入口。接上步,当p1==p2时,p2所经过节点数为2x,p1所经过节点数为x。 设环中有n个节点,p2比p1多走k圈有2x - x = nk;得 x=nk。可以看出p1实际走了k个环的步数。 再让p2指向链表头部,p1位置不变,p1、p2每次走一步,直到p1==p2,此时p1指向环的入口。
画图理解一波
代码如下:
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
*/
public class Solution {
public ListNode EntryNodeOfLoop(ListNode pHead)
{
if(pHead == null || pHead.next == null){
return null;
}
ListNode p1 = pHead;
ListNode p2 = pHead;
while(p2.next != null && p2 != null){
p2 = p2.next.next;
p1 = p1.next;
//if 语句表明快慢指针找到了相遇结点
if(p1 == p2){
//找到相同结点,p1指向开始结点
p2 = pHead;
while(p1 != p2){
p2 = p2.next;
p1 = p1.next;
}
if(p2 == p1){
return p1;
}
}
}
return null;
}
}