给你两个单链表的头节点
headA和headB,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回null。
解法1 暴力解法
思路
最暴力的解法就是遍历A链表同时逐个遍历B链表,如果相同则返回。
如果A走到最后则没有相交,则返回null节点。
代码
function getIntersectionNode(headA: ListNode | null, headB: ListNode | null): ListNode | null {
let currentA = headA;
while (currentA !== null) {
let currentB = headB;
while (currentB !== null) {
if (currentA === currentB) {
return currentA;
}
currentB = currentB.next;
}
currentA = currentA.next;
}
return null;
};
时空复杂度分析
时间复杂度:两层遍历,O(m * n)。该方法可以AC
空间复杂度:O(1)
题解2 哈希表缓存
思路
两层遍历时间复杂度过于高,我们可以利用空间缓存。
先遍历A链表用哈希表缓存下来,接下来遍历B链表逐个查询是否存在即可找到答案。
代码
function getIntersectionNode(headA: ListNode | null, headB: ListNode | null): ListNode | null {
let current = headA;
const hashSet = new Set();
while (current) {
hashSet.add(current);
current = current.next;
}
current = headB;
while (current) {
if (hashSet.has(current)) {
return current;
}
current = current.next;
}
return null;
};
时空复杂度分析
时间复杂度:两次遍历,O(m + n)
空间复杂度:使用哈希表缓存A链表,O(m)
解法3 双指针
思路
我们可以用两个指针,一个从A链表出发,如果走到链表末尾,则从B链表头重新出发。
另一个指针则相反,从B链表头出发,走到末尾再从A链表头出发。
如果有交点,则都走了 i + j + k 段,节点数相同。
如果没有交点,则都走了 i + j 段。最后走到队尾 null 节点。
代码
function getIntersectionNode(headA: ListNode | null, headB: ListNode | null): ListNode | null {
let currentA = headA;
let currentB = headB;
while (currentA !== currentB) {
currentA = currentA === null ? headB : currentA.next;
currentB = currentB === null ? headA : currentB.next;
}
return currentA;
};
时空复杂度分析
时间复杂度:O(m + n)
空间复杂度:O(1)