算法---相交链表

“ 今日继续算法相关的题目练习,坚持就是胜利,今日leetcode练习之相交链表。”

ps:今日涉及链表相关题目,在这里不对链表进行相关的介绍,不是很清楚的同学可以去网上搜索相关知识点做补充,之后再来看这道题。

1. 编写一个程序,找到两个单链表相交的起始节点

具体内容如下两幅图所示:
相交链表1
相交链表2

注意:

如果两个链表没有交点,返回 null.

在返回结果后,两个链表仍须保持原有的结构。

可假定整个链表结构中没有循环。

程序尽量满足 O(n) 时间复杂度,且仅用 O(1) 内存。

2. 方法一之Set

思路:
链表在相交的时候,表示两个链表中各自存在一个节点指向同一个地址,那么这个时候我们可以考虑将A或者B链表中的一个存入到Set对象中(假如是将A链表存入到Set对象中),接着将B链表中第一个节点拿出来看是否在Set中,如果不在的话,那么使用next找寻B链表中第二个节点,然后重复上面过程,如果找到则返回该值,如果没有找到则返回null。
注意:使用Set原因:因为存储的是对象,即可以通过地址进行查找,具有唯一性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* @param {ListNode} headA
* @param {ListNode} headB
* @return {ListNode}
*/
var getIntersectionNode = function(headA, headB) {
let set = new Set();
while (headA) {
set.add(headA);
headA = headA.next;
}
while(headB) {
if (set.has(headB)) return headB;
headB = headB.next;
}
return null;
};

这个时候我们会发现问题:
headA循环中假设m次循环完,headB循环中假设n次循环完,由于不知m还是n大,则这个时候时间复杂度为O(m+n),并且由于使用了Set,空间复杂度为O(m)或者O(n),看你是循环添加headA还是循环添加headB。

2. 补差法

思路:
有一个消差法,由于代码比较冗余这边不做解析,有兴趣的小伙伴可以看我在文章结尾给的参考地址,里面有消差的解析。
补差的思路其实就是:A+B=B+A,下面盗用了一张画的图解析过程:
补差法
其实不难看出通过补差法它们会在第二次的时候相遇。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* @param {ListNode} headA
* @param {ListNode} headB
* @return {ListNode}
*/
var getIntersectionNode = function(headA, headB) {
let currentA = headA;
let currentB = headB;
while (currentA !== currentB) {
currentA = currentA === null ? headB : currentA.next;
currentB = currentB === null ? headA : currentB.next;
}
return currentA;
};

感谢这位大佬给的解析,参考链接如下所示:

掘金–相交链表(JS)