思路一:用两个 map 分别记录 a b 走过的节点的指针,如果在对方的 map 里存在,则终止
func getIntersectionNode(headA, headB *ListNode) *ListNode {
mapA:=make(map[*ListNode]int)
mapB:=make(map[*ListNode]int)
nodeA:=headA
nodeB:=headB
for nodeA!=nil || nodeB!=nil{
if nodeA!=nil{
if _,ok:=mapB[nodeA];ok{
return nodeA
}
mapA[nodeA]=1
nodeA=nodeA.Next
}
if nodeB!=nil{
if _,ok:=mapA[nodeB];ok{
return nodeB
}
mapB[nodeB]=1
nodeB=nodeB.Next
}
}
return nil
}
思路二:双指针法
找出两个单链表相交的起始节点的一个有效方法是使用双指针技巧。该方法不需要额外的数据结构,也不会改变链表的原始结构,符合题目要求。其基本思路如下:
创建两个指针pA和pB,分别初始化为链表headA和headB的头节点。
同时遍历两个链表,当pA到达链表末尾时,将其重定位到链表headB的头节点;当pB到达链表末尾时,将其重定位到链表headA的头节点。
如果链表相交,pA和pB会在相交节点相遇;如果链表不相交,pA和pB会同时到达两个链表的末尾(都是null),这时退出循环。
这种方法的关键在于,通过重定位指针,使得pA和pB走过的路径长度相同。这样,如果链表相交,它们就会在相交节点相遇;如果不相交,它们会同时到达链表的末尾。
func getIntersectionNode(headA, headB *ListNode) *ListNode {
nodeA, nodeB := headA, headB
switchA, switchB := true, true
for nodeA!=nodeB && (nodeA != nil || nodeB != nil) {
if nodeA != nil {
if nodeA.Next == nil && switchA {
switchA = false
//不能这样写,否则直接将两个链表连接起来了
//nodeA.Next=headB
nodeA = headB
} else {
nodeA = nodeA.Next
}
}
if nodeB != nil {
if nodeB.Next == nil && switchB {
switchB = false
nodeB = headA
} else {
nodeB = nodeB.Next
}
}
}
if nodeA==nodeB{
return nodeA
}
return nil
}