題目:輸入兩個鏈表,找出它們的第一個公共結點。
思路1:暴力查找法。將鏈表1中的節點逐個與鏈表2中的所有節點比較,返回第一個相同的節點。複雜度O(mn)
class Solution {
public:
ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
if(pHead1 == nullptr || pHead2 == nullptr){
return nullptr;
}
ListNode* pNode1 = pHead1;
ListNode* pNode2 = pHead2;
ListNode* pCommonNode = nullptr;
while(pNode1->next != nullptr){
while(pNode2->next !=nullptr){
if(pNode1 != pNode2){
pNode2 = pNode2->next;
}
else{
pCommonNode = pNode1;
return pCommonNode;
break;
}
}
if(pCommonNode != nullptr){
break;
}
else{
pNode1 = pNode1->next;
}
}
return pCommonNode;
}
};
上述代碼沒有通過測試用例:具體原因是什麼呢???
思路2:上述方法的複雜度過高,並不是一個好方法。如果兩個鏈表有公共點,那麼公共節點出現在兩個鏈表的尾部。如果從兩個鏈表的尾部開始往前比較,那麼最後一個相同的節點就是我們要找的節點。因爲要從尾部開始比較,所以可以利用棧結構的“後進後出”:分別把兩個鏈表的節點放入兩個棧中,這樣兩個棧的尾節點就位於兩個棧的棧頂,接下來比較兩個棧頂的節點是否相同,相同則把棧頂彈出接着比較下一個棧頂,直到找到最後一個相同節點。這種方法是用空間消耗換取了時間效率。
class Solution {
public:
ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
if(pHead1 == nullptr || pHead2 == nullptr){
return nullptr;
}
std::stack<ListNode*> stack1;
std::stack<ListNode*> stack2;
while(pHead1 != nullptr){
stack1.push(pHead1);
pHead1=pHead1->next;
}
while(pHead2 != nullptr){
stack2.push(pHead2);
pHead2=pHead2->next;
}
ListNode* commonNode = nullptr;
while(!stack1.empty() && !stack2.empty()){
if(stack1.top() == stack2.top()){
commonNode = stack1.top();
stack1.pop();
stack2.pop();
}
}
return commonNode;
}
};
報錯:
思路3:首先遍歷兩個鏈表得到它們的長度,就能知道哪個鏈表比較長,以及長得鏈表比短的鏈表多幾個節點。在第二次遍歷的時候,在較長的鏈表上先走若干步,接着同時在兩個鏈表上遍歷,找到的第一個相同的節點就是它們的第一個公共節點。
class Solution {
public:
ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
unsigned int nLength1 = GetListLength(pHead1);
unsigned int nLength2 = GetListLength(pHead2);
int nLengthDif = nLength1 - nLength2;
ListNode* pListNodeLong = pHead1;
ListNode* pListNodeShort = pHead2;
if(nLength2>nLength1){
pListNodeLong = pHead2;
pListNodeShort = pHead1;
nLengthDif = nLength2 - nLength1;
}
for(int i = 1;i<nLengthDif+1;i++){
pListNodeLong = pListNodeLong->next;
}
while(pListNodeLong != nullptr && pListNodeShort != nullptr && pListNodeShort != pListNodeLong){
pListNodeLong = pListNodeLong->next;
pListNodeShort = pListNodeShort->next;
}
ListNode* pFirstCommonNode = pListNodeLong;
return pFirstCommonNode;
}
private:
unsigned int GetListLength(ListNode * pHead){
unsigned int nLength = 0;
ListNode* pNode = pHead;
while(pNode != nullptr){
nLength++;
pNode = pNode->next;
}
return nLength;
}
};