题目:输入两个链表,找出它们的第一个公共结点

来源:互联网 发布:单词朗读软件 知乎 编辑:程序博客网 时间:2024/05/29 11:54

题目:输入两个链表,找出它们的第一个公共结点。链表的定义如下:

struct ListNode

{

     int m_nValue;

     ListNode* m_pNext;

};


      看到这道题的时候很多的第一反应就是采用蛮力的方法:在第一个链表上顺序遍历每个节点,每遍历到一个节点的时候,在第二个链表上顺序遍历每个节点。如果第二个链表上的节点和第一个链表上的节点一样,就说明两个链表在节点上重合,于是就找到了公共的节点。而通常蛮力并不是好的方法。

      从链表的定义可以看出,这两个链表是单链表,如果两个链表有公共节点,那么这两个链表从某一节点开始,它们的m_pNext都指向同一个节点,之后它们所有的节点都是重合的,不可能再出现分叉。所以拓扑形状看起来是Y型。如下图所示:

 


一个简单的方法是:首先遍历两个链表得到它们的长度,就能知道哪个链表比较长,以及长的链表比短的链表多几个节点。在第二次遍历的时候,先在较长的节点上走若干步,接着同时在两个链表上遍历,找到的第一个相同的节点就是它们的公共的节点。该算法的时间复杂度为:O(m+n)。


完整代码及其测试用例如下:

#include<iostream>using namespace std;struct ListNode{int m_nValue;ListNode* m_pNext;};//创建链表节点ListNode* CreateListNode(int value){ListNode* pNode = new ListNode();pNode->m_nValue = value;pNode->m_pNext = NULL;return pNode;}//连接链表节点void ConnectListNodes(ListNode* pCurrent, ListNode* pNext){if (pCurrent == NULL){//exit(1),非正常运行导致退出程序;exit(0),正常运行并退出程序cout << "Error to connect two nodes." << endl;exit(1);}pCurrent->m_pNext = pNext;}//销毁链表void DestroyList(ListNode* pHead){ListNode* pNode = pHead;while (pNode!=NULL){pHead = pHead->m_pNext;delete pNode;pNode = pHead;}}//销毁节点void DestroyNode(ListNode* pNode){delete pNode;pNode = NULL;}//求链表的长度unsigned int GetListLength(ListNode* pHead){unsigned int nLength = 0;ListNode* pNode = pHead;while (pNode!=NULL){nLength++;pNode = pNode->m_pNext;}return nLength;}//找第一个公共节点ListNode* FindFirstCommonNode(ListNode *pHead1, ListNode *pHead2){//求两个链表的长度unsigned int nLength1 = GetListLength(pHead1);unsigned int nLength2 = GetListLength(pHead2);//两个链表的长度差int nLengthDif = nLength1 - nLength2;ListNode* pListHeadLong = pHead1;ListNode* pListHeadShort= pHead2;if (nLength2 > nLength1){pListHeadLong = pHead2;pListHeadShort = pHead1;nLengthDif = nLength2 - nLength1;}// 先在长链表上走几步,再同时在两个链表上遍历for (int i = 0; i < nLengthDif; i++){pListHeadLong = pListHeadLong->m_pNext;}while ((pListHeadLong!=NULL)&& (pListHeadShort != NULL)&&(pListHeadLong != pListHeadShort)){pListHeadLong = pListHeadLong->m_pNext;pListHeadShort = pListHeadShort->m_pNext;}//得到第一个公共节点ListNode* pFisrtCommonNode = pListHeadLong;//ListNode* pFisrtCommonNode = pListHeadShort;也可以return pFisrtCommonNode;}// ====================测试代码====================void Test(char* testName, ListNode* pHead1, ListNode* pHead2, ListNode* pExpected){if (testName != NULL){cout << testName << "  begins: ";}ListNode* pResult = FindFirstCommonNode(pHead1, pHead2);if (pResult == pExpected){cout << "Succeed!" << endl;}else{cout << "Failed!" << endl;}}// 第一个公共结点在链表中间// 1 - 2 - 3 \//                6 - 7//      4 - 5 /void Test1(){ListNode* pNode1 = CreateListNode(1);ListNode* pNode2 = CreateListNode(2);ListNode* pNode3 = CreateListNode(3);ListNode* pNode4 = CreateListNode(4);ListNode* pNode5 = CreateListNode(5);ListNode* pNode6 = CreateListNode(6);ListNode* pNode7 = CreateListNode(7);ConnectListNodes(pNode1, pNode2);ConnectListNodes(pNode2, pNode3);ConnectListNodes(pNode3, pNode6);ConnectListNodes(pNode4, pNode5);ConnectListNodes(pNode5, pNode6);ConnectListNodes(pNode6, pNode7);Test("Test1", pNode1, pNode4, pNode6);DestroyNode(pNode1);DestroyNode(pNode2);DestroyNode(pNode3);DestroyNode(pNode4);DestroyNode(pNode5);DestroyNode(pNode6);DestroyNode(pNode7);}// 没有公共结点// 1 - 2 - 3 - 4//            // 5 - 6 - 7void Test2(){ListNode* pNode1 = CreateListNode(1);ListNode* pNode2 = CreateListNode(2);ListNode* pNode3 = CreateListNode(3);ListNode* pNode4 = CreateListNode(4);ListNode* pNode5 = CreateListNode(5);ListNode* pNode6 = CreateListNode(6);ListNode* pNode7 = CreateListNode(7);ConnectListNodes(pNode1, pNode2);ConnectListNodes(pNode2, pNode3);ConnectListNodes(pNode3, pNode4);ConnectListNodes(pNode5, pNode6);ConnectListNodes(pNode6, pNode7);Test("Test2", pNode1, pNode5, NULL);DestroyList(pNode1);DestroyList(pNode5);}// 公共结点是最后一个结点// 1 - 2 - 3 - 4 \//                      7//           5 - 6 /void Test3(){ListNode* pNode1 = CreateListNode(1);ListNode* pNode2 = CreateListNode(2);ListNode* pNode3 = CreateListNode(3);ListNode* pNode4 = CreateListNode(4);ListNode* pNode5 = CreateListNode(5);ListNode* pNode6 = CreateListNode(6);ListNode* pNode7 = CreateListNode(7);ConnectListNodes(pNode1, pNode2);ConnectListNodes(pNode2, pNode3);ConnectListNodes(pNode3, pNode4);ConnectListNodes(pNode4, pNode7);ConnectListNodes(pNode5, pNode6);ConnectListNodes(pNode6, pNode7);Test("Test3", pNode1, pNode5, pNode7);DestroyNode(pNode1);DestroyNode(pNode2);DestroyNode(pNode3);DestroyNode(pNode4);DestroyNode(pNode5);DestroyNode(pNode6);DestroyNode(pNode7);}// 公共结点是第一个结点// 1 - 2 - 3 - 4 - 5// 两个链表完全重合   void Test4(){ListNode* pNode1 = CreateListNode(1);ListNode* pNode2 = CreateListNode(2);ListNode* pNode3 = CreateListNode(3);ListNode* pNode4 = CreateListNode(4);ListNode* pNode5 = CreateListNode(5);ConnectListNodes(pNode1, pNode2);ConnectListNodes(pNode2, pNode3);ConnectListNodes(pNode3, pNode4);ConnectListNodes(pNode4, pNode5);Test("Test4", pNode1, pNode1, pNode1);DestroyList(pNode1);}// 输入的两个链表有一个空链表void Test5(){ListNode* pNode1 = CreateListNode(1);ListNode* pNode2 = CreateListNode(2);ListNode* pNode3 = CreateListNode(3);ListNode* pNode4 = CreateListNode(4);ListNode* pNode5 = CreateListNode(5);ConnectListNodes(pNode1, pNode2);ConnectListNodes(pNode2, pNode3);ConnectListNodes(pNode3, pNode4);ConnectListNodes(pNode4, pNode5);Test("Test5", NULL, pNode1, NULL);DestroyList(pNode1);}// 输入的两个链表都是空链表void Test6(){Test("Test6", NULL, NULL, NULL);}int main(){Test1();Test2();Test3();Test4();Test5();Test6();system("pause");return 0;}


运行结果:

Test1  begins: Succeed!

Test2  begins: Succeed!

Test3  begins: Succeed!

Test4  begins: Succeed!

Test5  begins: Succeed!

Test6  begins: Succeed!

请按任意键继续. . .

      

0 0