相交链表

24 阅读1分钟

思路一:用两个 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
}