题目:
输入两个链表,找出它们的第一个公共结点。
链接:
剑指Offer(第2版):P253
思路标签:
- 算法:空间换时间
解答:
寻求高效的时间效率和空间效率
- 除了嵌套循环的复杂解法。通过分析题目,可以知道在第一个公共节点后面所有的节点都是公共节点,如果可以从后向前遍历,那么最后一个相同的节点即时我们要寻找的节点。但是单向链表无法从后向前遍历,只能从前向后遍历。所以这是一种栈的形式,后进先出。所以我们可以使用两个栈来从前向后遍历两个链表,再从栈中依次弹出比较,最后一个相同的节点即时我们要寻找的节点。时间复杂度O(m+n),空间复杂度O(m+n)。
- 另外一种简单的方法:遍历链表求得两个链表各自的长度;因为两个链表的最后部分是重叠的,所以先让长的链表走几步,相同后同时向前遍历。过程中节点相同的时候,即为第一个公共节点。时间复杂度O(m+n),但不需要辅助栈。
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public:
ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
unsigned int nLength1 = GetListLength(pHead1);
unsigned int nLength2 = GetListLength(pHead2);
int nLengthDiff = nLength1 - nLength2;
ListNode* pListHeadLong = pHead1;
ListNode* pListHeadShort = pHead2;
if(nLength1 < nLength2){
pListHeadLong = pHead2;
pListHeadShort = pHead1;
nLengthDiff = nLength2 - nLength1;
}
for(int i=0; i<nLengthDiff; ++i)
pListHeadLong = pListHeadLong->next;
while(pListHeadLong != nullptr && pListHeadShort != nullptr && pListHeadShort != pListHeadLong){
pListHeadLong = pListHeadLong->next;
pListHeadShort = pListHeadShort->next;
}
if(pListHeadLong != nullptr)
return pListHeadLong;
else
return nullptr;
}
unsigned int GetListLength(ListNode* pHead){
unsigned int nLength = 0;
ListNode* pNode = pHead;
while(pNode != nullptr){
++nLength;
pNode = pNode->next;
}
return nLength;
}
};