面试题30:两个链表的第一个公共结点

来源:互联网 发布:知乎专栏有稿费吗 编辑:程序博客网 时间:2024/05/29 11:03

分析:从链表结点的定义看,两个链表是单向链表。如果两个单向链表有公共结点,那么这两个链表从某一结点开始,他们的m_pNext都指向同一个结点。从第一个公共结点开始,之后它们所有结点都是重合的,不可能再出现分叉。

例如:

方法一:分别把两个链表的结点放入两个栈中,这样两个链表的尾结点就位于两个栈的栈顶,然后比较两个栈顶的结点是否相同。若相同,则把栈顶弹出接着比较下一个栈顶,直到找到最后一个相同的结点。

空间复杂度:O(n1+n2), 因为需要两个辅助栈。时间复杂度:O(n1+n2)

方法二:首先遍历两个链表得到他们的长度,在第二次遍历时,在较长的链表上先走若干步,接着再同时在两个链表上遍历,找到第一个相同的结点就是他们的第一个公共结点。

时间复杂度:O(n1+n2), 不需要额外的辅助空间。

代码:

#include "stdafx.h"#include <iostream>#include <stack>using namespace std;//链表中的结点类型struct ListNode{int m_nKey;ListNode *m_pNext;};//创建一个链表,输入-1表示结束void CreateLinkedList(ListNode *&pHeadNode){bool isHeadNode = true;ListNode *pListNode = NULL;ListNode *pCurrentTail = NULL;while (1){if (isHeadNode){   pHeadNode = new ListNode();cin >> pHeadNode->m_nKey;pHeadNode->m_pNext = NULL;pCurrentTail = pHeadNode;isHeadNode = false;}else{pListNode = new ListNode();cin >> pListNode->m_nKey;if (pListNode->m_nKey == -1){break;}pListNode->m_pNext = NULL;pCurrentTail->m_pNext = pListNode;pCurrentTail = pListNode;}}}//求链表的长度int ListLength(ListNode *pHead){int nLength = 0;    ListNode *pCur = pHead;while (pCur != NULL){nLength++;pCur = pCur->m_pNext;}return nLength;}//销毁一个链表void DestoryList(ListNode *pHeadNode){ListNode *pNode = pHeadNode;ListNode *pNext = NULL;while (pNode != NULL){pNext = pNode->m_pNext;delete pNode;pNode = pNext;}     pHeadNode = NULL;cout << "链表已被销毁!" << endl;}//从头到尾打印链表void PrintList(ListNode *pHead){if (pHead != NULL){ListNode *pCurNode = pHead;cout << "从头到尾打印链表:"; while (pCurNode != NULL){cout << pCurNode->m_nKey << " ";pCurNode = pCurNode->m_pNext;}cout << endl;}}//从尾到头打印链表void PrintLinkedListReversely(ListNode *pHead){stack<ListNode *> tempStack;if (pHead != NULL){ListNode *pCurrent = pHead;ListNode *pStackNode = NULL;while (pCurrent != NULL){tempStack.push(pCurrent);pCurrent = pCurrent->m_pNext;}cout << "从尾到头打印链表:"; while (!tempStack.empty()){pStackNode = tempStack.top();cout << pStackNode->m_nKey << " ";tempStack.pop();}cout << endl;}}//找到两个链表的第一个公共结点ListNode *FindFirstCommonNode(ListNode *pHead1, ListNode *pHead2){ListNode *pFirstCommonNode = NULL;    int nLength1 = ListLength(pHead1);int nLength2 = ListLength(pHead2);int nLengthDiff = 0;//两个链表长度的差值ListNode *pLong = NULL;ListNode *pShort = NULL;if (nLength1 > nLength2){nLengthDiff = nLength1 - nLength2;pLong = pHead1;pShort = pHead2;}else{nLengthDiff = nLength2 - nLength1;pLong = pHead2;pShort = pHead1;}int i = 0;while (i < nLengthDiff){   pLong = pLong->m_pNext;   i++;}while (pLong != NULL && pShort != NULL && pLong->m_nKey != pShort->m_nKey){pLong = pLong->m_pNext;pShort = pShort->m_pNext;}pFirstCommonNode = pLong;return pFirstCommonNode;}int _tmain(int argc, _TCHAR* argv[]){//创建第一个链表    ListNode *pHead1 = NULL;CreateLinkedList(pHead1);PrintList(pHead1);    //创建第二个链表ListNode *pHead2 = NULL;CreateLinkedList(pHead2);PrintList(pHead2);    cout << "两个链表的第一个公共结点是:" << FindFirstCommonNode(pHead1, pHead2)->m_nKey << endl;//销毁两个链表DestoryList(pHead1);    DestoryList(pHead2);system("pause");return 0;}
运行结果:



原创粉丝点击