160、相交链表
给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。
图示两个链表在节点 c1 开始相交:
方法一:哈希表
1.1 思路分析
用哈希表记录访问过的地址,如果再次访问时哈希表中已存在,则说明该结点就是相交点。
注意点:
- 两条链表不能改动,所以要定义两个辅助变量a, b保存headA, headB
- 要考虑其中一条先到头的情况
1.2 代码实现
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func getIntersectionNode(headA, headB *ListNode) *ListNode {
// 哈希表
visited := make(map[*ListNode]bool)
a, b := headA, headB
for a != nil || b != nil{
if a != nil{
if _, has := visited[a]; has{
return a
}
visited[a] = true
a = a.Next
}
if b != nil{
if _, has := visited[b]; has{
return b
}
visited[b] = true
b = b.Next
}
}
return nil
}
1.3 测试结果
1.4 复杂度
- 时间复杂度:O(m+n)
- 空间复杂度:O(m+n)
方法二:双指针
2.1 思路分析
不使用额外的空间,就不能再用哈希表记录访问过的位置了。这里使用双指针的方法,将两条链构成环,最终必会相遇。
2.2 代码实现
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func getIntersectionNode(headA, headB *ListNode) *ListNode {
a, b := headA, headB
for {
if a == b{
return a
}
if a == nil{
a = headB
}else if b == nil{
b = headA
}else{
a = a.Next
b = b.Next
}
}
return nil
}
2.3 测试结果
2.4 复杂度
- 时间复杂度:O(m+n)
- 空间复杂度:O(1)