casyup.me@outlook.com

0%

leetcode/160IntersectionofTwoLinkedList

Intersection of two linked list

获得两条链表的连接点

my solution (36ms, 100%)

(虽然效率看起来是最好的, 但是其实比起最好的算法要差不少)

核心难点在于两条链表的长度不一定相等, 这样就不能遍历节点用等于的形式来判断

那么拿到两条链表的长度, 让较长的链表前进若干次, 以达到长度相等的情形, 那么就可以遍历了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
int deep_A = 0, deep_B = 0;

ListNode *temp_head = headA;
while (temp_head) {
temp_head = temp_head->next;
++deep_A;
}

temp_head = headB;
while (temp_head) {
temp_head = temp_head->next;
++deep_B;
}

int distance = abs(deep_A - deep_B);
if (deep_A > deep_B) {
while (distance) {
headA = headA->next;
--distance;
}
} else {
while (distance) {
headB = headB->next;
--distance;
}
}

while (headA && headB && headA != headB) {
headA = headA->next;
headB = headB->next;
}

return headA;
}
};

代码如下, 会产生 3 次遍历, 两次完整的遍历 O(3n) => O(n)

the best solution

1
2
3
4
5
6
7
8
9
10
11
12
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode *p = headA;
ListNode *q = headB;
while (p != q) {
p = (p ? p->next: headB);
q = (q ? q->next: headA);
}
return p;
}
};

原来还可以这么做!!!

算法的核心思想在于, A + B = B + A

假设有两条链表, 长度不等

0 0 0 2 1 1    // A
0 0 2 1 1    // B

其中将他们的链接点标为 2

那么有以下组合链表

0 0 0 2 1 1 0 0 2 1 1    // A + B
0 0 2 1 1 0 0 0 2 1 1    // B + A

他们如果有链接点, 那么在第二次循环时必然相等

我是用求深度差来解决这个问题, 这个算法更加巧妙地用组合链表的形式规避了这个深度差