链表-2 链表中环的入口节点
解法1:循环(空间复杂度非O(1))
思路是:从头开始遍历每个节点,并把每个已访问节点存入“已访问节点列表”visited_Node中。
当最新访问的节点在“已访问节点列表”中出现时,则最新访问的节点为该链表中环的入口;若整个链表的节点都没出现在““已访问节点列表””中,则该链表无环。
class Solution: def EntryNodeOfLoop(self, pHead): visited_Node = []; if pHead is None: return None; while pHead is not None: if pHead in visited_Node: return pHead; visited_Node.append(pHead); pHead = pHead.next; return None; 运行时间:27ms 占用内存:5852k
缺点:需要定义额外的存储空间,存“已访问节点列表”。
解法2:快慢指针法+双指针法(未想到,空间复杂度O(1))
思路是:拆解问题。将“求链表中环的入口节点”拆分为3个小问题:
①确定链表中是否有环(快慢指针法);
②若有环,则需找到环中的任意一个节点p,并确定环中的总节点个数;
③从节点p开始,找到环的入口节点(双指针法)。
class Solution: def EntryNodeOfLoop(self, pHead): if pHead is None or pHead.next is None: return None; else: # 1.确定链表中是否有环(快慢指针法) p_slow = pHead.next; p_fast = pHead.next.next; while p_fast != p_slow: if p_fast is None: return None; p_slow = p_slow.next; p_fast = p_fast.next.next; p = p_fast; # p记录的是慢指针和快指针相遇时对应的那个链表节点; # p节点若存在,则必定在环中。 # 2.计算环中的总节点个数k k = 1; p_flag = p.next; while p_flag != p: k = k + 1; p_flag = p_flag.next; # 3.确定环的入口(双指针法,做法:令指针p1从头结点先多走k步,此时p1到达第(1+k)个节点;然后令指针p2从头节点开始走,指针p1、p2的前进速度相同。当指针p1、p2相遇时,它们指向的节点恰好为环的入口结点。 # 未想到的点:指针p2从头结点走到环的入口节点,走了(n-k)步;此时指针p1到达的位置为(k+1)+(n-k)=(n+1),即为环的入口节点,p1、p2正好相遇。) i = 0; p1 = pHead; while i < k: p1 = p1.next; i = i+1; p2 = pHead; while p1 != p2: p1 = p1.next; p2 = p2.next; return p2; 第一次运行 解法2: 运行时间:31ms 占用内存:5816k 第二次运行 解法2: 运行时间:28ms 占用内存:5748k
浙公网安备 33010602011771号