输入分为2段,第一段是入环前的链表部分,第二段是链表环的部分,后台会根据第二段是否为空将这两段组装成一个无环或者有环单链表
返回链表的环的入口结点即可,我们后台程序会打印这个结点对应的结点值;若没有,则返回对应编程语言的空结点即可。
{1,2},{3,4,5}
3
返回环形链表入口结点,我们后台程序会打印该环形链表入口结点对应的结点值,即3
{1},{}
"null"
没有环,返回对应编程语言的空结点,后台程序会打印"null"
{},{2}
2
环的部分只有一个结点,所以返回该环形链表入口结点,后台程序打印该结点对应的结点值,即2
class Solution: def EntryNodeOfLoop(self, pHead): vessel = set() while pHead: if pHead in vessel: return pHead else: vessel.add(pHead) pHead = pHead.next return pHead习惯用数组,数组太慢过不了,改成集合
# -*- coding:utf-8 -*- # class ListNode: # def __init__(self, x): # self.val = x # self.next = None class Solution: def getListLen(self,head): pos=head n=0 while pos is not None: n+=1 pos=pos.next return n def EntryNodeOfLoop(self, pHead): # write code here if pHead is None&nbs***bsp;pHead.next is None: return None slow = pHead fast = pHead while slow.next and fast.next.next: # temp = slow slow = slow.next fast = fast.next.next if slow is fast: nHead = slow.next # temp.next = None # 断开 slow.next = None len1 = self.getListLen(pHead) len2 = self.getListLen(nHead) if len1>len2: for i in range(len1-len2): pHead=pHead.next else: for i in range(len2-len1): nHead=nHead.next while True: if pHead is nHead: return pHead pHead=pHead.next nHead=nHead.next return 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 is None: return None p1=pHead p2=pHead ##确定是否有环 num=0 while p2.next and p2.next.next and num==0: p2=p2.next.next p1=p1.next if p1.val==p2.val: p=p1 num+=1 if num==0: return None ##确定环的节点数n p=p.next n=1 while p.val!=p1.val: n+=1 p=p.next p3=pHead p4=pHead for i in range(n): p3=p3.next while p3.val !=p4.val: p3=p3.next p4=p4.next return p3跟着剑指一步一步走
python解法:
解法1:哈希表;
class Solution: def EntryNodeOfLoop(self, pHead): hash = {} while pHead: if pHead not in hash: hash[pHead] = 1 else: return pHead pHead = pHead.next return None
解法2:快慢指针,妙啊~
快指针一次走两步,满指针一次走一步,相遇后停止;
之后再用一个指针从头出发,同时慢指针再继续走,两者相遇的地方即环入口;
具体讲解见图:
class Solution: def EntryNodeOfLoop(self, pHead): slow, fast = pHead, pHead while fast and fast.next: fast = fast.next.next slow = slow.next if slow == fast: break if not fast or not fast.next: return None p = pHead while p != slow: p = p.next slow = slow.next return p
# -*- coding:utf-8 -*- # class ListNode: # def __init__(self, x): # self.val = x # self.next = None class Solution: def EntryNodeOfLoop(self, pHead): # write code here slow,fast = pHead,pHead while fast and fast.next: slow = slow.next fast = fast.next.next if fast == slow: slow = pHead while slow!=fast: slow = slow.next fast = fast.next return slow
# -*- 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 not pHead&nbs***bsp;not pHead.next: return None Node1 = pHead.next Node2 = pHead.next.next while Node1 != Node2: if Node1.next.next and Node2.next: Node1 = Node1.next.next Node2 = Node2.next else: return None # 确定环的长度 TempNode = Node1.next LoopLength = 1 while TempNode != Node1: TempNode = TempNode.next LoopLength += 1 # 确定环的入口 Node1 = pHead Node2 = pHead i = LoopLength while i: Node1 = Node1.next i -= 1 while Node1 != Node2: Node1 = Node1.next Node2 = Node2.next return Node1
class Solution: def EntryNodeOfLoop(self, pHead): # write code here if pHead == None: return None pTmp = pHead set1 = set() while pTmp: if pTmp in set1: return pTmp set1.add(pTmp) pTmp = pTmp.next return None
借用楼上图说明一下
主要思路:
1.fast指针一次2个next,slow 一次一个next
2.确认有环:fast与slow重合
3.确定环节点:前面重合点继续slow到下一次又重合
4.初始位置相隔k个点,再一次相遇就是入口
其实也可以不用计算k
fast = slow + ring = 2*slow
slow = ring
因此上面直接可以进行第三步,直接让一个指针从头开始,当两个指针重回时,即为入口
# -*- 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 == None: return None # 确认有环 fast = pHead slow = pHead while fast: if fast.next: fast = fast.next.next slow = slow.next if not fast: return None if fast == slow: break # 找到环的节点数 # 上面的相遇点一定是在环内,因此在环内循环一圈就能找到节点数 k = 0 while fast: fast = fast.next k += 1 if fast == slow: break fast = pHead slow = pHead for i in range(k): fast = fast.next # 前后相隔k个点,同时相同速度,相交点就是入口 while fast: if fast == slow: break fast = fast.next slow = slow.next return fast
# -*- coding:utf-8 -*- # class ListNode: # def __init__(self, x): # self.val = x # self.next = None class Solution: def EntryNodeOfLoop(self, pHead): slow,fast = pHead,pHead while fast and fast.next : slow = slow.next fast = fast.next.next if slow == fast: slow2 = pHead while slow != slow2: slow = slow.next slow2 = slow2.next return slow
class Solution: def EntryNodeOfLoop(self, pHead): #如果链表为空 if not pHead: return None #s保存遍历过的节点,s初始值为第一个节点 s = {pHead} #从第二个节点开始遍历 p = pHead.next #p不为空,为空说明没环 while p: #如果p指向的节点不在集合s中,把p添加到s中,p接着指向下一个节点 if p not in s: s.add(p) p = p.next #如果p指向的节点在集合s中,说明有环,且入口就是p else: return p return 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 tmp_list = [] p = pHead while p: if p in tmp_list: return p else: tmp_list.append(p) p = p.next
# -*- coding:utf-8 -*- # class ListNode: # def __init__(self, x): # self.val = x # self.next = None class Solution: def EntryNodeOfLoop(self, pHead): # write code here visited = [] while pHead: if pHead in visited: return pHead else: visited.append(pHead) pHead = pHead.next return None
class Solution:
def EntryNodeOfLoop(self, pHead):
# write code here
if pHead==None or pHead.next==None or pHead.next.next==None:
return None
slow=pHead
fast=pHead
while slow.next!=None and fast.next.next!=None:
slow=slow.next
fast=fast.next.next
if slow==fast:
isLinkedListContainsLoop=True
break
if isLinkedListContainsLoop:
slow=pHead
while slow!=fast:
slow=slow.next
fast=fast.next
return slow
return null
class Solution: def EntryNodeOfLoop(self, pHead): # write code here # record the path if pHead == None: return None sy = [] p = pHead while p != None: for i in sy: if i == p.next: return i sy.append(p) p = p.next return None我的思路比较直接,用一个数组记录指针走过节点的地址(即指针数组),没走下一步前判断下一个节点在不在路径中,若在,则下一个节点就是环的入口。
包含三个问题:
class ListNode: def __init__(self, x): self.val = x self.next = None class Solution: def EntryNodeOfLoop(self, pHead): if pHead == None: return None else: p1 = pHead p2 = p1 #p1 different speed while(p1.next!=None and p1.next.next!=None): p1 = p1.next p2 = p2.next.next if p1 == p2: break # no cycle if p1.next == None or p1.next.next == None: return None else: # the number of nodes in cycle nCycle = 1 p2 = p2.next while(p2 != p1): p2 = p2.next nCycle += 1 # the entrance p1 = pHead p2 = pHead for i in range(nCycle): p2 = p2.next while(p1 != p2): p1 = p1.next p2 = p2.next return p1 p1 = ListNode(1) p1.next = ListNode(2) p1.next.next = ListNode(3) p1.next.next.next = ListNode(4) p1.next.next.next.next = ListNode(5) p1.next.next.next.next.next = p1.next.next s =Solution() s.EntryNodeOfLoop(p1)
当第二个指针指向环的入口结点时,第一个指针已经围绕着环走了一圈又回到了入口结点。