剑指offer36:两个链表的第一个公共结点

1 题目描述

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

2 思路和方法

  方法一:

  用两个指针同时从两个链表的表头开始走,当走到自己的链表结尾的时候开始从另一个链表的表头开始向后走。终止条件就是两个指针第一次相遇。此时指针位置即为所求。(两个链表的节点和是一定的,所以两个指针一定可以同时遍历完两条链表,即在最后时刻两个指针一定是重合的)

  方法2:

  先数出两条链表的长度,得到长度差d,先将长链表从头结点往后走d步,之后第二个链表从头开始,两个链表一起一步一步走,直到两个链表的节点第一次相等为止,此时指针位置即为所求。

3 C++核心代码

1 ListNode* FindFirstCommonNode( ListNode *pHead1, ListNode *pHead2) {
2         ListNode *p1 = pHead1;
3         ListNode *p2 = pHead2;
4         while(p1!=p2){
5             p1 = (p1==NULL ? pHead2 : p1->next);
6             p2 = (p2==NULL ? pHead1 : p2->next);
7         }
8         return p1;
9     }
View Code
 1     ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
 2         ListNode *p1=pHead1;
 3         ListNode *p2=pHead2;
 4         int len1=0,len2=0,diff=0;
 5         while(p1!=NULL){
 6             p1=p1->next;
 7             len1++;
 8         }
 9         while(p2!=NULL){
10             p2=p2->next;
11             len2++;
12         }
13         if(len1>len2){
14             diff=len1-len2;
15             p1=pHead1;
16             p2=pHead2;
17         }
18         else{
19             diff=len2-len1;
20             p1=pHead2;
21             p2=pHead1;
22         }
23         for(int i=0;i<diff;i++){
24             p1=p1->next;
25         }
26         while(p1!=NULL && p2!=NULL){
27             if(p1==p2)
28                 break;
29             p1=p1->next;
30             p2=p2->next;
31         }
32         return p1;
33     }
View Code

4 C++完整代码

  1 #include<iostream>
  2 using namespace std;
  3  
  4 struct ListNode
  5 {
  6     int m_nValue;
  7     ListNode* m_pNext;
  8 };
  9  
 10 //创建链表节点
 11 ListNode* CreateListNode(int value)
 12 {
 13     ListNode* pNode = new ListNode();
 14     pNode->m_nValue = value;
 15     pNode->m_pNext = NULL;
 16  
 17     return pNode;
 18 }
 19  
 20  
 21 //连接链表节点
 22 void ConnectListNodes(ListNode* pCurrent, ListNode* pNext)
 23 {
 24     if (pCurrent == NULL)
 25     {
 26         //exit(1),非正常运行导致退出程序;exit(0),正常运行并退出程序
 27         cout << "Error to connect two nodes." << endl;
 28         exit(1);
 29     }
 30  
 31     pCurrent->m_pNext = pNext;
 32 }
 33  
 34  
 35 //销毁链表
 36 void DestroyList(ListNode* pHead)
 37 {
 38     ListNode* pNode = pHead;
 39  
 40     while (pNode!=NULL)
 41     {
 42         pHead = pHead->m_pNext;
 43         delete pNode;
 44         pNode = pHead;
 45     }
 46 }
 47  
 48 //销毁节点
 49 void DestroyNode(ListNode* pNode)
 50 {
 51     delete pNode;
 52     pNode = NULL;
 53 }
 54  
 55 //求链表的长度
 56 unsigned int GetListLength(ListNode* pHead)
 57 {
 58     unsigned int nLength = 0;
 59     ListNode* pNode = pHead;
 60  
 61     while (pNode!=NULL)
 62     {
 63         nLength++;
 64         pNode = pNode->m_pNext;
 65     }
 66  
 67     return nLength;
 68 }
 69  
 70 //找第一个公共节点
 71 ListNode* FindFirstCommonNode(ListNode *pHead1, ListNode *pHead2)
 72 {
 73     //求两个链表的长度
 74     unsigned int nLength1 = GetListLength(pHead1);
 75     unsigned int nLength2 = GetListLength(pHead2);
 76     //两个链表的长度差
 77     int nLengthDif = nLength1 - nLength2;
 78     ListNode* pListHeadLong = pHead1;
 79     ListNode* pListHeadShort= pHead2;
 80     if (nLength2 > nLength1)
 81     {
 82         pListHeadLong = pHead2;
 83         pListHeadShort = pHead1;
 84         nLengthDif = nLength2 - nLength1;
 85     }
 86  
 87     // 先在长链表上走几步,再同时在两个链表上遍历
 88     for (int i = 0; i < nLengthDif; i++)
 89     {
 90         pListHeadLong = pListHeadLong->m_pNext;
 91     }
 92  
 93     while ((pListHeadLong!=NULL)&& (pListHeadShort != NULL)&&(pListHeadLong != pListHeadShort))
 94     {
 95         pListHeadLong = pListHeadLong->m_pNext;
 96         pListHeadShort = pListHeadShort->m_pNext;
 97     }
 98  
 99     //得到第一个公共节点
100     ListNode* pFisrtCommonNode = pListHeadLong;
101     //ListNode* pFisrtCommonNode = pListHeadShort;也可以
102  
103     return pFisrtCommonNode;
104 }
105  
106  
107 // ====================测试代码====================
108 void Test(char* testName, ListNode* pHead1, ListNode* pHead2, ListNode* pExpected)
109 {
110     if (testName != NULL)
111     {
112         cout << testName << "  begins: ";
113     }
114  
115     ListNode* pResult = FindFirstCommonNode(pHead1, pHead2);
116     if (pResult == pExpected)
117     {
118         cout << "Succeed!" << endl;
119     }
120     else
121     {
122         cout << "Failed!" << endl;
123     }
124 }
125  
126  
127 // 第一个公共结点在链表中间
128 // 1 - 2 - 3 \
129 //                6 - 7
130 //      4 - 5 /
131 void Test1()
132 {
133     ListNode* pNode1 = CreateListNode(1);
134     ListNode* pNode2 = CreateListNode(2);
135     ListNode* pNode3 = CreateListNode(3);
136     ListNode* pNode4 = CreateListNode(4);
137     ListNode* pNode5 = CreateListNode(5);
138     ListNode* pNode6 = CreateListNode(6);
139     ListNode* pNode7 = CreateListNode(7);
140  
141     ConnectListNodes(pNode1, pNode2);
142     ConnectListNodes(pNode2, pNode3);
143     ConnectListNodes(pNode3, pNode6);
144     ConnectListNodes(pNode4, pNode5);
145     ConnectListNodes(pNode5, pNode6);
146     ConnectListNodes(pNode6, pNode7);
147  
148     Test("Test1", pNode1, pNode4, pNode6);
149  
150     DestroyNode(pNode1);
151     DestroyNode(pNode2);
152     DestroyNode(pNode3);
153     DestroyNode(pNode4);
154     DestroyNode(pNode5);
155     DestroyNode(pNode6);
156     DestroyNode(pNode7);
157 }
158  
159 // 没有公共结点
160 // 1 - 2 - 3 - 4
161 //            
162 // 5 - 6 - 7
163 void Test2()
164 {
165     ListNode* pNode1 = CreateListNode(1);
166     ListNode* pNode2 = CreateListNode(2);
167     ListNode* pNode3 = CreateListNode(3);
168     ListNode* pNode4 = CreateListNode(4);
169     ListNode* pNode5 = CreateListNode(5);
170     ListNode* pNode6 = CreateListNode(6);
171     ListNode* pNode7 = CreateListNode(7);
172  
173     ConnectListNodes(pNode1, pNode2);
174     ConnectListNodes(pNode2, pNode3);
175     ConnectListNodes(pNode3, pNode4);
176     ConnectListNodes(pNode5, pNode6);
177     ConnectListNodes(pNode6, pNode7);
178  
179     Test("Test2", pNode1, pNode5, NULL);
180  
181     DestroyList(pNode1);
182     DestroyList(pNode5);
183 }
184  
185 // 公共结点是最后一个结点
186 // 1 - 2 - 3 - 4 \
187 //                      7
188 //           5 - 6 /
189 void Test3()
190 {
191     ListNode* pNode1 = CreateListNode(1);
192     ListNode* pNode2 = CreateListNode(2);
193     ListNode* pNode3 = CreateListNode(3);
194     ListNode* pNode4 = CreateListNode(4);
195     ListNode* pNode5 = CreateListNode(5);
196     ListNode* pNode6 = CreateListNode(6);
197     ListNode* pNode7 = CreateListNode(7);
198  
199     ConnectListNodes(pNode1, pNode2);
200     ConnectListNodes(pNode2, pNode3);
201     ConnectListNodes(pNode3, pNode4);
202     ConnectListNodes(pNode4, pNode7);
203     ConnectListNodes(pNode5, pNode6);
204     ConnectListNodes(pNode6, pNode7);
205  
206     Test("Test3", pNode1, pNode5, pNode7);
207  
208     DestroyNode(pNode1);
209     DestroyNode(pNode2);
210     DestroyNode(pNode3);
211     DestroyNode(pNode4);
212     DestroyNode(pNode5);
213     DestroyNode(pNode6);
214     DestroyNode(pNode7);
215 }
216  
217 // 公共结点是第一个结点
218 // 1 - 2 - 3 - 4 - 5
219 // 两个链表完全重合   
220 void Test4()
221 {
222     ListNode* pNode1 = CreateListNode(1);
223     ListNode* pNode2 = CreateListNode(2);
224     ListNode* pNode3 = CreateListNode(3);
225     ListNode* pNode4 = CreateListNode(4);
226     ListNode* pNode5 = CreateListNode(5);
227  
228     ConnectListNodes(pNode1, pNode2);
229     ConnectListNodes(pNode2, pNode3);
230     ConnectListNodes(pNode3, pNode4);
231     ConnectListNodes(pNode4, pNode5);
232  
233     Test("Test4", pNode1, pNode1, pNode1);
234  
235     DestroyList(pNode1);
236 }
237  
238 // 输入的两个链表有一个空链表
239 void Test5()
240 {
241     ListNode* pNode1 = CreateListNode(1);
242     ListNode* pNode2 = CreateListNode(2);
243     ListNode* pNode3 = CreateListNode(3);
244     ListNode* pNode4 = CreateListNode(4);
245     ListNode* pNode5 = CreateListNode(5);
246  
247     ConnectListNodes(pNode1, pNode2);
248     ConnectListNodes(pNode2, pNode3);
249     ConnectListNodes(pNode3, pNode4);
250     ConnectListNodes(pNode4, pNode5);
251  
252     Test("Test5", NULL, pNode1, NULL);
253  
254     DestroyList(pNode1);
255 }
256  
257 // 输入的两个链表都是空链表
258 void Test6()
259 {
260     Test("Test6", NULL, NULL, NULL);
261 }
262  
263  
264 int main()
265 {
266     Test1();
267     Test2();
268     Test3();
269     Test4();
270     Test5();
271     Test6();
272     system("pause");
273     return 0;
274 }
View Code

参考资料

https://blog.csdn.net/lingfeng2019/article/details/80778598

https://blog.csdn.net/yanxiaolx/article/category/6250534(完整代码)

posted @ 2019-08-27 22:41  wxwreal  阅读(192)  评论(0编辑  收藏  举报