今日你如约而至了吗?坚持每天至少一道,不至于手生哦。上题:
题目描述
给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
分析:有两种方法 哈希法, 双指针法
方法一:哈希法:遍历链表,不存在则存入哈希表中,存在则表明有环,输出。
代码:
import java.util.Set;
import java.util.HashSet;
/*
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)return pHead;
Set<ListNode> set = new HashSet<>();
while(pHead!=null){
if(set.contains(pHead)){ //如果之前出现过,则直接输出
return pHead;
}else{
set.add(pHead); //如果没有,则添加到哈希表中;
}
pHead=pHead.next;
}
return null;
}
}
牛客运行通过
运行时间:13ms
运行内存:9536Kb
这种方法还是比较好理解的。
方法二:双指针法:
找一个快慢指针,slow和fast,slow走1步,fast走2步;
如果存在环,两个快慢指针一定在环中相遇;
相遇时,让fast回到头结点,开始走1步,slow继续走,两人再相遇即为环入口。
链接里有很好的示意图:
https://blog.nowcoder.net/n/deaa284f105e48f49f38b5d7cb809cd7?f=comment
两者相遇,快指针可能在环中环游了好几圈,但是走的长度依旧是一样的。
代码:
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
*/
public class Solution {
public ListNode EntryNodeOfLoop(ListNode pHead){
ListNode slow = pHead;
ListNode fast = pHead;
while((fast!=null)&&(fast.next!=null)){
slow = slow.next;
fast = fast.next.next; //slow走一步,fast走两步,直到相遇,停止;
if(slow==fast){
break;
}
}
if((fast==null)||(fast.next==null))return null;
fast = pHead; //fast回到头结点
while(slow!=fast){
slow = slow.next; //slow和fast一起走一步;
fast = fast.next;
}
return fast;
}
}
牛客运行通过
运行时间:15ms
运行内存:9632Kb
快慢指针的方法是比较简单的,主要要理解其中的相遇后,两指针的距离;
快慢指针在链表中应用比较多,例如:求链表倒数k个结点;
欢迎各位互相学习和交流哦~