题目描述
给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
解题思路
此题有两种思路来做:
第一种:利用HashSet()储存节点
从链表头节点开始,依次将链表每一个节点存入到hashset中,并检查每次存入的元素是否已经在hashset中重复出现,因为链表中存在环的结构,当某一次检查到当前将要add的节点已在hashset中存在时,该节点即为链表的入环节点。可能有人已经发现了一些小问题,对的,这种方法必须针对链表元素没有重复出现的情况才能适用!
第二种:设置快慢指针(一般方法)
这种方法适用任何情况,包括元素重复出现。这题的思想和寻找链表倒数第K个节点有些相似,本题中,我们假设快指针每次移动两步,而慢指针每次移动一步。如果链表有环形结构,其两个指针一定会在环内相遇,相遇后,我们在重新设定一个指针从头节点出发,而慢指针则在相遇点继续出发,两指针移动速度相同,每次都移动一步,则当两指针相遇时,一定会在链表的入环节点处!
图示
当快指针P1和慢指针P2,同时从头节点‘1’出发时,第一次在节点**‘5’处相遇**。慢指针P2在‘5’处移动,而P1从头节点‘1’开始移动,两指针速度保持一致,最后第二次在节点‘3’,也是链表的入环节点处相遇。
代码实现
去博客设置页面,选择一款你喜欢的代码片高亮样式,下面展示同样高亮的 代码片
.
import java.util.HashSet;
class ListNode{ //定义链表节点
ListNode next;
int val;
public ListNode(ListNode listNode,int val){
this.val=val;
this.next=listNode;
}
public ListNode(){}
}
public class entryNodeOfLoop {
//用快慢指针寻找链表环形的入口
public ListNode entryOfLoop_1(ListNode pHead){
if (pHead==null||pHead.next==null){
return null;
}
ListNode slow=pHead;
ListNode fast=pHead;
while (fast!=null&&fast.next!=null){
slow=slow.next;//慢指针一次走一步
fast=fast.next.next;//快指针一次走两步
if (slow==fast){//快慢指针重合位置(只有有环就一定会在环内相遇)
break;
}
}
if (fast==null || fast.next==null){
return null;
}
ListNode newStart=pHead;//重新定义一个指针从头节点出发
while (slow!=null&&newStart!=null){
if (slow==newStart){//pHead与slow相遇在环的入口节点处
return slow;
}
slow=slow.next;
newStart=newStart.next;
}
return null;
}
public ListNode entryOfLoop_2(ListNode pHead){
HashSet<ListNode> pSet=new HashSet<>();
while (pHead!=null){
if (pSet.contains(pHead)){
return pHead;
}
pSet.add(pHead);
pHead=pHead.next;
}
return null;
}
public static void main(String[] args) {
ListNode first = new ListNode();
ListNode second = new ListNode();
ListNode third = new ListNode();
ListNode fourth = new ListNode();
first.val = 1; first.next = second;
second.val = 2; second.next = third;
third.val = 3; third.next = fourth;
fourth.val = 4; fourth.next = second;
entryNodeOfLoop entry=new entryNodeOfLoop();
ListNode node=entry.entryOfLoop_1(first);
System.out.println(node);
}
}
总结
本题来源于面试经典教材《剑指offer》中 归属于链表类型题目。
同许多在算法道路上不断前行的人一样,不断练习,修炼自己!
如有博客中存在的疑问或者建议,可以在下方留言一起交流,感谢各位!
最后,感谢Jerry算法!