题目描述
输入两个链表,找出它们的第一个公共结点。
思路
公共节点指的是节点的指针相同(节点本身相同),而不是节点的内容相同。
如果考虑暴力的方法,对于链表1的每个元素,去遍历链表2,找出第一个公共节点,这样时间复杂度为O(mn),计算开销大;(m,n分别为两个链表的长度)
考虑具有公共节点的链表的特征:如果两个链表有公共节点,则两个链表会形成“Y”的形状,在公共节点后,两个链表是相同的。
(1)这时候我们可以考虑在遍历的时候用两个栈去存在两个链表的元素,然后依次对两个栈进行弹栈操作,最后一个相同的元素即是第一个公共节点;
该方法时间复杂度为O(m+n);空间复杂度也是O(m+n)
(1)考虑效率更高的方法。我们先通过一次遍历得到两个链表的长度len1和len2。假设len1>len2,重新遍历两个链表时,让链表1先走len1-len2步,这样两个链表的剩余长度相同。然后同时开始遍历,找出公共节点。
时间复杂度为O(m+n),且不需要额外的空间开销。
代码
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public: // 时间复杂度O(n)
ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
if(pHead1== nullptr || pHead2 == nullptr)
return nullptr;
ListNode *pNode1 = pHead1;
ListNode *pNode2 = pHead2;
int len1 = 0;
int len2 = 0;
while (pNode1!= nullptr){ // 计算第一个链表长度
++len1;
pNode1 = pNode1->next;
}
while (pNode2!= nullptr){ // 计算第一个链表长度
++len2;
pNode2 = pNode2->next;
}
pNode1 = pHead1;
pNode2 = pHead2;
int i = 0;
// 让较长链表先走一段距离;使两个链表剩余长度相等
if (len1>len2){
while (i< len1 - len2){
pNode1 = pNode1->next;
++i;
}
} else if(len1<len2){
while (i< len2 - len1){
pNode2 = pNode2->next;
++i;
}
}
while (pNode1!= nullptr && pNode2!= nullptr){
if(pNode1 == pNode2)
return pNode1;
pNode1 = pNode1->next;
pNode2 = pNode2->next;
}
return nullptr;
}
};