题目
代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
}
};
方法一:哈希表
分析
寻找链表是否相交,可以使用哈希表存储链表节点,并
我们遍历链表
A
A
A 和
B
B
B 的每个元素对比哈希表中元素。
- 当前元素不在哈希表中,将当前元素存入哈希表;
- 当前元素在哈希表中,返回当前元素;
- 如果链表 A A A 和 B B B 遍历结束,则两个链表不相交,返回 n u l l null null。
代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
unordered_set<ListNode*> hash;
while(headA != nullptr || headB != nullptr) {
if(headA != nullptr) {
if(hash.count(headA)) {
return headA;
} else {
hash.insert(headA);
}
headA = headA->next;
}
if(headB != nullptr) {
if(hash.count(headB)) {
return headB;
} else {
hash.insert(headB);
}
headB = headB->next;
}
}
return nullptr;
}
};
复杂度分析
- 时间复杂度: O ( m a x ( m , n ) ) O(max(m,n)) O(max(m,n)),其中 m m m, n n n 是链表 A A A, B B B 的长度。哈希表可以在 O ( 1 ) O(1) O(1) 的时间进行查找。
- 空间复杂度: O ( m + n ) O(m+n) O(m+n),空间复杂度主要取决于哈希表,哈希表中存储 A A A, B B B 两个链表的元素,最多有 m + n m+n m+n 个元素。
分析
对以上代码进行优化,我们可以先遍历链表 A A A 的每个元素并存储到哈希表中;之后遍历链表 B B B 的每个元素进行查找。
- 当前元素不在哈希表中,遍历下一个元素;
- 当前元素在哈希表中,返回当前元素;
- 如果链表 B B B 遍历结束,则两个链表不相交,返回 n u l l null null。
代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
unordered_set<ListNode*> hash;
while(headA != nullptr) {
hash.insert(headA);
headA = headA->next;
}
while(headB != nullptr) {
if(hash.count(headB))
return headB;
headB = headB->next;
}
return nullptr;
}
};
复杂度分析
- 时间复杂度: O ( m + n ) O(m+n) O(m+n),其中 m m m, n n n 是链表 A A A, B B B 的长度。哈希表可以在 O ( 1 ) O(1) O(1) 的时间进行查找。
- 空间复杂度: O ( m ) O(m) O(m),需要使用哈希集合存储链表 链表 A A A 中的全部元素。
方法二:双指针
分析
假设链表
A
A
A,
B
B
B 存在交链长度
c
c
c,设链表
A
A
A 长度为
m
=
a
+
c
m=a+c
m=a+c 链表
B
B
B 长度为
n
=
b
+
c
n=b+c
n=b+c 使用指针
t
e
m
p
A
tempA
tempA 先遍历链表
A
A
A 后遍历链表
B
B
B;使用指针
t
e
m
p
B
tempB
tempB 先遍历链表
B
B
B 后遍历链表
A
A
A,指针
t
e
m
p
A
tempA
tempA 和指针
t
e
m
p
B
tempB
tempB 走过的路径长度为:
m
+
n
=
a
+
b
+
2
c
m+n=a+b+2c
m+n=a+b+2c 由于链表
A
A
A,
B
B
B 存在交点,最后指针
t
e
m
p
A
tempA
tempA、
t
e
m
p
B
tempB
tempB 必然走了相同路径
c
c
c, 当指针
t
e
m
p
A
=
t
e
m
p
B
tempA=tempB
tempA=tempB 时,即指针
t
e
m
p
A
tempA
tempA、
t
e
m
p
B
tempB
tempB同时指向链表交点时,指针
t
e
m
p
A
tempA
tempA、
t
e
m
p
B
tempB
tempB 走过的路径长度为:
a
+
b
+
c
a+b+c
a+b+c 返回指针
t
e
m
p
A
tempA
tempA。
特殊情况:当两个链表不相交时,即交链长度
c
=
0
c=0
c=0,指针
t
e
m
p
A
tempA
tempA 、
t
e
m
p
B
tempB
tempB 走过的路径长度为:
m
+
n
=
a
+
b
m+n=a+b
m+n=a+b 当指针
t
e
m
p
A
=
t
e
m
p
B
tempA=tempB
tempA=tempB 时,指针
t
e
m
p
A
tempA
tempA、
t
e
m
p
B
tempB
tempB同时指向
n
u
l
l
null
null,返回
n
u
l
l
null
null。
代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode *tempA = headA, *tempB = headB;
while(tempA != tempB) {
tempA = tempA == nullptr ? headB : tempA->next;
tempB = tempB == nullptr ? headA : tempB->next;
}
return tempA;
}
};
复杂度分析
- 时间复杂度: O ( m + n ) O(m+n) O(m+n),其中 m m m, n n n 是链表 A A A, B B B 的长度。
- 空间复杂度: O ( 1 ) O(1) O(1)。