[leetCode][003] Intersection of Two Linked Lists
【题目】:
Write a program to find the node at which the intersection of two singly linked lists begins.
For example, the following two linked lists:
A: a1 → a2
↘
c1 → c2 → c3
↗
B: b1 → b2 → b3
begin to intersect at node c1.
Notes:
1. If the two linked lists have no intersection at all, return null.
2. The linked lists must retain their original structure after the function returns.
3. You may assume there are no cycles anywhere in the entire linked structure.
4. Your code should preferably run in O(n) time and use only O(1) memory
【题意解析】:
输入两个单链表,判断这两个单链表是否相交,返回相交点。这里有几种方法供大家参考。
【解法1】
《编程之美》一书中有讲到该问题,如何判断这两个链表相交,可以讲其中一个链表的头尾相连,然后从另一个链表的角度来判断时候有环状链表存在即可。相当于将问题转换成如何求有环单链表的环状入口点?详细方案见我的另一篇专门讲环状单链表的文章 《关于有环单链表的那些事儿》。需要注意的是,不能改变原有链表的结构,因此方法返回的时候需要恢复原状。
(1)将链表B的尾节点指向其头节点HeadB,因此链表B形成环状,链表A成为有环单链表;
(2)此时问题转换成求链表A上环状入口点;
(3)恢复链表B的结构;
代码如下:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
if (nullptr == headA || nullptr == headB){
return nullptr;
} ListNode *pNode = headB;
while (pNode->next){
pNode = pNode->next;
}
ListNode *pRear = pNode;
pNode->next = headB; ListNode *pJoint = loopJoint(headA);
pRear->next = nullptr; // 恢复 return pJoint;
} private:
ListNode *loopJoint(ListNode *pHead){
if (nullptr == pHead || nullptr == pHead->next){
return nullptr;
} ListNode *pSlow = pHead;
ListNode *pFast = pHead;
while (pFast && pFast->next){
pFast = pFast->next->next;
pSlow = pSlow->next; if (pFast == pSlow){
break;
}
} if (nullptr == pFast || nullptr == pFast->next){
return nullptr;
} pSlow = pHead;
while (pFast != pSlow){
pFast = pFast->next;
pSlow = pSlow->next;
} return pSlow;
}
};

【解法2】
《剑指Offer》一书中提到的这个方法,如果两个没有环的链表相交于某个节点,那么在这个节点之后的所有节点都是两个链表所共有的。因此两个链表从交织点之前的部分长度差即为整条链表的长度差,我们只要让两条链表从离交织点相同距离的位置开始前进,经过O(n)步,一定能够找到交织点。
(1)遍历链表A,记录其长度len1,遍历链表B,记录其长度len2。
(2)按尾部对齐,如果两个链表的长度不相同,让长度更长的那个链表从头节点先遍历abs(len1-en2),这样两个链表指针指向对齐的位置。
(3)然后两个链表齐头并进,当它们相等时,就是交集的节点。
时间复杂度O(n+m),空间复杂度O(1)
代码如下:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
if (nullptr == headA || nullptr == headB){
return nullptr;
} int nLongLength = ;
int nShortLength = ;
ListNode *pLongList = headA;
ListNode *pShortList = headB; while (pLongList){
++nLongLength;
pLongList = pLongList->next;
} while (pShortList){
++nShortLength;
pShortList = pShortList->next;
} if (nShortLength > nLongLength){
pLongList = headB;
pShortList = headA; // 校正
nLongLength ^= nShortLength;
nShortLength ^= nLongLength;
nLongLength ^= nShortLength;
}
else{
pLongList = headA;
pShortList = headB;
} // int offset = (nLongLength - nShortLength > 0) ? (nLongLength - nShortLength) : (nShortLength - nLongLength);
int offset = nLongLength - nShortLength;
while (offset> ){
pLongList = pLongList->next;
--offset;
} while (pLongList != pShortList){
pLongList = pLongList->next;
pShortList = pShortList->next;
} return pLongList;
}
};

【解法3】
还有一种解法,实际上还是利用步差来实现的,具体证明还米有搞懂,思考中。具体如下:
(1)维护两个指针pA和pB,初始分别指向链表A和链表B。然后让它们分别遍历整个链表,每步一个节点。
(2)当pA到达链表末尾时,让它指向B的头节点;类似的当pB到达链表末尾时,重新指向A的头节点。
(3)当pA和pB相遇时也即为交织点。
该算法的时间复杂度依然为O(m + n),时间复杂度为O(1)
代码如下:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
if (nullptr == headA || nullptr == headB){
return nullptr;
} ListNode *nodeA = headA;
ListNode *nodeB = headB;
while (nodeA && nodeB && nodeA != nodeB){
nodeA = nodeA->next;
nodeB = nodeB->next; if (nodeA == nodeB){
break;
} if (nullptr == nodeA){
nodeA = headB;
} if (nullptr == nodeB){
nodeB = headA;
}
} return nodeA;
}
};

如果错误,希望各位不吝赐教,谢谢
[leetCode][003] Intersection of Two Linked Lists的更多相关文章
- [LeetCode] 160. Intersection of Two Linked Lists 解题思路
Write a program to find the node at which the intersection of two singly linked lists begins. For ex ...
- [LeetCode]160.Intersection of Two Linked Lists(2个链表的公共节点)
Intersection of Two Linked Lists Write a program to find the node at which the intersection of two s ...
- LeetCode 160. Intersection of Two Linked Lists (两个链表的交点)
Write a program to find the node at which the intersection of two singly linked lists begins. For ex ...
- [LeetCode] 160. Intersection of Two Linked Lists 求两个链表的交集
Write a program to find the node at which the intersection of two singly linked lists begins. For ex ...
- 【leetcode】Intersection of Two Linked Lists
题目简述: Write a program to find the node at which the intersection of two singly linked lists begins. ...
- Leetcode 160. Intersection of two linked lists
Write a program to find the node at which the intersection of two singly linked lists begins. For ex ...
- Java for LeetCode 160 Intersection of Two Linked Lists
Write a program to find the node at which the intersection of two singly linked lists begins. For ex ...
- ✡ leetcode 160. Intersection of Two Linked Lists 求两个链表的起始重复位置 --------- java
Write a program to find the node at which the intersection of two singly linked lists begins. For ex ...
- leetcode:Intersection of Two Linked Lists(两个链表的交叉点)
Write a program to find the node at which the intersection of two singly linked lists begins. For ex ...
随机推荐
- 让jar程序在linux上一直执行
当我们把java程序打成jar包后,放到linux上通过putty或其它终端执行的时候,如果按照:java -jar xxxx.jar执行,当我们退出putty或终端的时候,xxxx.jar这个程序也 ...
- python4delphi 设置syspath
详细看demo25的代码 These techniques are demonstrated in Demo25 in the examples folder of your Python for D ...
- OJ 1188 全排列---康托展开
题目描述 求n的从小到大第m个全排列(n≤20). 输入 n和m 输出 输出第m个全排列,两个数之间有一空格. 样例输入 3 2 样例输出 1 3 2 #include<cstdio> # ...
- 【GoLang】GoLang fmt 占位符详解
golang 的fmt 包实现了格式化I/O函数,类似于C的 printf 和 scanf. # 定义示例类型和变量 type Human struct { Name string } var peo ...
- HTML控件ID和NAME属性及在CS页面获得.ASPX页面中HTML控件的值
<转载>来自网络 一.ID是在客户端脚本里用!NAME是用于获取提交表单的某表单域信息,在form里面,如果不指定Name的话,就不会发送到服务器端,所以有name属性的控件,必须指定na ...
- mysql 我的学习
安装要求 安装环境:CentOS-6.3安装方式:源码编译安装 软件名称:mysql-cluster-gpl-7.2.6-linux2.6-x86_64.tar.gz下载地址:http://mysql ...
- dt.jar设计时rt.jar运行时
很多人在初学Java的时候,都要配置环境变量.在配置CLASSPATH的时候,都会加上一个当前目录.,还有两个jar:dt.jar和tools.jar.其实好多人都不了解这两个jar的作用,尤其是dt ...
- MFC中添加消息响应函数
转自:http://blog.csdn.net/eddy_liu/article/details/8474677 目前,用MFC设计的Windows应用程序几乎都采用文档/视图结构.这种程序框架与简单 ...
- 爱改名的小融 2(codevs 3149)
3149 爱改名的小融 2 时间限制: 2 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 查看运行结果 题目描述 Description Wikioi上有个人 ...
- 如何 ︰ 执行批量更新和插入使用.NET 提供程序在 C#.NET OpenXML
https://support.microsoft.com/zh-cn/kb/315968 如何 ︰ 执行批量更新和插入使用.NET 提供程序在 C#.NET OpenXML Email Prin ...