题目:输入两个链表,找出它们的第一个公共结点。
思路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;
}
};