链表中环的入口结点——题解
链表中环的入口结点
http://www.nowcoder.com/questionTerminal/253d2c59ec3e4bc68da16833f79a38e4
方法一:使用set,遍历链表,如果存在一个已经存在的node,那就说明有环了,此时,返回该节点;否则,当跳出while循环时,说明没有环,则返回None。
# -*- coding:utf-8 -*- # class ListNode: # def __init__(self, x): # self.val = x # self.next = None class Solution: def EntryNodeOfLoop(self, pHead): # write code here if pHead.next == None: return None nodes = set() while pHead.next is not None: if pHead not in nodes: nodes.add(pHead) pHead = pHead.next else: return pHead return None方法二:快慢指针,其实这个题目我最早想到的是使用快慢指针。无奈理解不够透彻,写的快慢指针有问题,所以无奈有了上述方法一(使用老流氓set)
思路:定义两个指针slow和fast,不断移动这两个指针,slow指针移动的步长是1,而fast指针移动的步长是2.
如果存在环,则slow指针和fast指针一定会相遇,此时输出该节点。
否则判断fast指针的next是否为空,如果为空的话,说明快指针已经到了链表的尾部,该链表无环。 那判断有环之后怎么确定环的入口节点呢?借鉴官方题解的快慢指针做法。地址:https://blog.nowcoder.net/n/9d3ffa4b004e43d1aff512141d0d7dac
重点理解为什么在第一次相遇之后要将fast指针移动到开头!官方题解中公式推导。
/*
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;
if (slow == fast)
break;
}
// 判断跳出循环的原因:如果是break的话就是有环,如果是因为不满足while判别条件那就是没有环
if (fast ==null || fast.next == null) return null; // 因为不满足while条件而跳出的
// 得到环的入口节点
fast = pHead;
while(slow != fast){
fast = fast.next;
slow = slow.next;
}
return fast;
}
} 快慢指针应用场景:判断是否有环,环的入口,删除倒数第k个元素,找到中间值;
查看7道真题和解析