1 题目描述

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

2 思路和方法

  方法一:

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

  方法2:

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

3 C++核心代码

 ListNode* FindFirstCommonNode( ListNode *pHead1, ListNode *pHead2) {
ListNode *p1 = pHead1;
ListNode *p2 = pHead2;
while(p1!=p2){
p1 = (p1==NULL ? pHead2 : p1->next);
p2 = (p2==NULL ? pHead1 : p2->next);
}
return p1;
}
     ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
ListNode *p1=pHead1;
ListNode *p2=pHead2;
int len1=,len2=,diff=;
while(p1!=NULL){
p1=p1->next;
len1++;
}
while(p2!=NULL){
p2=p2->next;
len2++;
}
if(len1>len2){
diff=len1-len2;
p1=pHead1;
p2=pHead2;
}
else{
diff=len2-len1;
p1=pHead2;
p2=pHead1;
}
for(int i=;i<diff;i++){
p1=p1->next;
}
while(p1!=NULL && p2!=NULL){
if(p1==p2)
break;
p1=p1->next;
p2=p2->next;
}
return p1;
}

4 C++完整代码

 #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();
} 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 = ;
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 = ; 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();
ListNode* pNode2 = CreateListNode();
ListNode* pNode3 = CreateListNode();
ListNode* pNode4 = CreateListNode();
ListNode* pNode5 = CreateListNode();
ListNode* pNode6 = CreateListNode();
ListNode* pNode7 = CreateListNode(); 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 - 7
void Test2()
{
ListNode* pNode1 = CreateListNode();
ListNode* pNode2 = CreateListNode();
ListNode* pNode3 = CreateListNode();
ListNode* pNode4 = CreateListNode();
ListNode* pNode5 = CreateListNode();
ListNode* pNode6 = CreateListNode();
ListNode* pNode7 = CreateListNode(); 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();
ListNode* pNode2 = CreateListNode();
ListNode* pNode3 = CreateListNode();
ListNode* pNode4 = CreateListNode();
ListNode* pNode5 = CreateListNode();
ListNode* pNode6 = CreateListNode();
ListNode* pNode7 = CreateListNode(); 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();
ListNode* pNode2 = CreateListNode();
ListNode* pNode3 = CreateListNode();
ListNode* pNode4 = CreateListNode();
ListNode* pNode5 = CreateListNode(); ConnectListNodes(pNode1, pNode2);
ConnectListNodes(pNode2, pNode3);
ConnectListNodes(pNode3, pNode4);
ConnectListNodes(pNode4, pNode5); Test("Test4", pNode1, pNode1, pNode1); DestroyList(pNode1);
} // 输入的两个链表有一个空链表
void Test5()
{
ListNode* pNode1 = CreateListNode();
ListNode* pNode2 = CreateListNode();
ListNode* pNode3 = CreateListNode();
ListNode* pNode4 = CreateListNode();
ListNode* pNode5 = CreateListNode(); 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 ;
}

参考资料

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

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

剑指offer36:两个链表的第一个公共结点的更多相关文章

  1. 剑指Offer 两个链表的第一个公共结点

    题目描述 输入两个链表,找出它们的第一个公共结点.   思路: 题目说的很笼统,应该是有2个链表,找出公共点,第一个公共点后面的链表是共同所有的.可以用map做,直接检测map里有没有出现这个节点. ...

  2. 剑指Offer——两个链表的第一个公共结点

    题目描述: 输入两个链表,找出它们的第一个公共结点. 分析: 设置两个指针,分别从两个链表的头部开始往后遍历. 谁遍历完自己本身的,就从另一个链表开始遍历,这样大家到达第一个公共结点的时候便会相遇. ...

  3. 剑指offer--44.两个链表的第一个公共结点

    @selfboot 牛逼的代码,长度相同,一遍出结果, 长度不同,短的点跑完,变成长的,当长的跑完变成短的链表的时候,较长的链表已经走过了多的结点. ------------------------- ...

  4. 剑指Offer-35.两个链表的第一个公共结点(C++/Java)

    题目: 输入两个链表,找出它们的第一个公共结点. 分析: 先统计两个链表的长度,计算他们的差值,然后将两个链表对齐,再去寻找公共节点即可. 程序: C++ class Solution { publi ...

  5. 用js刷剑指offer(两个链表的第一个公共结点)

    题目描述 输入两个链表,找出它们的第一个公共结点. 牛客网链接 js代码 /*function ListNode(x){ this.val = x; this.next = null; }*/ fun ...

  6. C++版 - 剑指offer之面试题37:两个链表的第一个公共结点[LeetCode 160] 解题报告

    剑指offer之面试题37 两个链表的第一个公共结点 提交网址: http://www.nowcoder.com/practice/6ab1d9a29e88450685099d45c9e31e46?t ...

  7. 剑指Offer - 九度1505 - 两个链表的第一个公共结点

    剑指Offer - 九度1505 - 两个链表的第一个公共结点2013-11-24 20:09 题目描述: 输入两个链表,找出它们的第一个公共结点. 输入: 输入可能包含多个测试样例.对于每个测试案例 ...

  8. 剑指Offer(三十六):两个链表的第一个公共结点

    剑指Offer(三十六):两个链表的第一个公共结点 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn.ne ...

  9. 【剑指Offer面试编程题】题目1505:两个链表的第一个公共结点--九度OJ

    题目描述: 输入两个链表,找出它们的第一个公共结点. 输入: 输入可能包含多个测试样例. 对于每个测试案例,输入的第一行为两个整数m和n(1<=m,n<=1000):代表将要输入的两个链表 ...

  10. 《剑指offer》第五十二题(两个链表的第一个公共结点)

    // 面试题52:两个链表的第一个公共结点 // 题目:输入两个链表,找出它们的第一个公共结点. #include <iostream> #include "List.h&quo ...

随机推荐

  1. mapper @Select()注解开发,使用模板 if 和循环

    if @Select({"<script>", "SELECT " + " mu.id userId, " + " e ...

  2. java一周学习回顾

    快速阅读 ​ 本周在学习java过程中主要是快马观花,对java的常用框架进行相关配置 ,进行简单的调用 .包括kafka,dubbo ,zookeeper.centos配置java环境.如何打war ...

  3. Linux后台运行任务

    [Linux]ssh命令行下多任务前后台切换 原文:https://my.oschina.net/huxuanhui/blog/13844 我们都知道,在 Windows 上面,我们要么让一个程序作为 ...

  4. qt 添加程序插件目录

    QApplication::addLibraryPath(QApplication::applicationDirPath()); QApplication::addLibraryPath(QAppl ...

  5. OpenJudge计算概论-奇数求和

    /*=================================================== 奇数求和 总时间限制: 1000ms 内存限制: 65536kB 描述 计算非负整数 m 到 ...

  6. 0.9.0.RELEASE版本的spring cloud alibaba nacos实例

    简而言之,nacos与eureka的不同之处有三:后台老板.部署方式.功能.nacos是阿里的,eureka是奈飞的:nacos有自己的安装包,需要独立部署,eureka仅作为一个服务组件,引入jar ...

  7. Promise和Generator

    异同: 1.promise解决的是串行的嵌套异步问题. 2.yield把Generator Function切割为有多个出口的Generation. 3.Promise是社区的研发产物,yield是E ...

  8. linux简单命令4---压缩与解压

    1:压缩命令:zip 2:.gz压缩,不能压缩目录,会压缩目录里的文件 3:.bz2压缩,不能压缩目录,直接报错 ------------------------------------------- ...

  9. Python SciPy库——插值与拟合

    插值与拟合 原文链接:https://zhuanlan.zhihu.com/p/28149195 1.最小二乘拟合 实例1 # -*- coding: utf-8 -*- import numpy a ...

  10. Delphi下Treeview控件基于节点编号的访问1

    有时我们需要保存和重建treeview控件,本文提供一种方法,通过以树结构节点的编号访问树结构,该控件主要提供的方法如下:      function GetGlobeNumCode(inNode:T ...