题目:有两个较长的单向链表a和b,为了找出节点node满足node in a并且node in b,请设计空间使用尽量小的算法。
来源:阿里巴巴 2014秋校园招聘 软件研发 笔试卷 27题
思路:若两个链表有公共部分,则这两个链表的结构类似于Y型。首先遍历两个链表到尾指针同时记下两个链表的长度m, n,若尾指针不同,则没有公共链表。然后使用两个指针重头遍历,让长链表的指针先走|m-n|步,使得当遇到公共节点的时候,快慢指针能同时到达。整体复杂度为O(m+n)。
代码如下:
#include <iostream>
using namespace std;
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
class Solution {
public:
ListNode *commonList(ListNode *h1, ListNode *h2) {
int m = 0, n = 0;
ListNode *cur1 = h1, *cur2 = h2;
while(cur1->next != NULL) {
m++;
cur1 = cur1->next;
}
while(cur2->next != NULL) {
n++;
cur2 = cur2->next;
}
//若链表的尾节点不同,则没有公共链表
if(cur1 != cur2)
return NULL;
cur1 = h1, cur2 = h2;
int dis = m > n ? m-n : n-m;
//较长的链表先走dis步
if(m >= n) {
while(dis--)
cur1 = cur1->next;
}
else {
while(dis--)
cur2 = cur2->next;
}
while(cur1 != NULL && cur2 != NULL) {
if(cur1 == cur2)
return cur1;
cur1 = cur1->next;
cur2 = cur2->next;
}
}
};
int main() {
//测试
ListNode *head1 = new ListNode(1);
head1->next = new ListNode(4);
head1->next->next = new ListNode(3);
ListNode *head2 = new ListNode(2);
head2->next = new ListNode(5);
head2->next->next = head1->next;
head2->next->next->next = head1->next->next;
Solution s;
ListNode *res = s.commonList(head1, head2);
while(res != NULL) {
cout << res->val << " ";
res = res->next;
}
while(head1 != NULL) {
ListNode *tmp = head1;
head1 = head1->next;
delete tmp;
}
while(head2 != NULL) {
ListNode *tmp = head2;
head2 = head2->next;
delete tmp;
}
return 0;
}