[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 ...
随机推荐
- delphi 2007 远程调试
Remote debugging lets you debug a RAD Studio application running on a remote computer. Once the remo ...
- javascript quine
javascript有一些奇怪的性质,恩,比如说,非常容易写一个quine,即自己输出自己代码的东西. function a(){console.log(a.toString()+";a() ...
- 《ASP.NET1200例》未能找到元数据文件解决办法
今天在做一个项目的时候,遇到这样的一个问题,我用的是三层结构的.未能找到元数据文件“D:\SYSTEM\桌面\MyExam\MyExam\MyExamBLL\bin\Debug\BLL.dl ...
- malloc/free vs new/delete
malloc/new是库函数. new/delete是运算符. 对于非内部数据类型的对象而言,光用malloc/free 无法满足动态对象的要求.对象在创建的同时要自动执行构造函数, 对象在消亡之前要 ...
- shell脚本批量生成配置文件
如果管理的站点和服务器较多的情况下,每次修改配置文件都相当痛苦.因而想到了用shell脚本来批量生成配置文件和配置数据.下面这个脚本是为了批量生成nagios监控配置文件的一个shell脚本程序.其原 ...
- python 的类变量和对象变量
python是一种解释性的语言,任何变量可以在使用的时候才声明以及定义,也可以在程序运行的任何位置进行声明和定义新的变量. class Man(object): #直接定义的类的变量,属于类 #其中 ...
- python基础——字符串和编码
python基础——字符串和编码 字符串也是一种数据类型,但是,字符串比较特殊的是还有一个编码问题. 因为计算机只能处理数字,如果要处理文本,就必须先把文本转换为数字才能处理.最早的计算机在设计时采用 ...
- c++ static及const(开发者在线)
static 是c++中很常用的修饰符,它被用来控制变量的存储方式和可见性,下面我将从 static 修饰符的产生原因.作用谈起,全面分析static 修饰符的实质. static 的两大作用: 一. ...
- Maven使用笔记(三)Maven的工作原理
概述 Maven是一个项目管理工具,他包含了一个项目对象模型,一组标准集合,一个项目生命周期,一个依赖管理系统和用来运行定义生命周期阶段中插件目标的逻辑. Maven是基于约定优于配置的思想来管理代码 ...
- 有哪些关于 Android 开发的博客值得订阅?
链接:http://www.zhihu.com/question/19788650/answer/60771437来源:知乎 Google 官方[Android Developers Blog](An ...