【题目】:  

  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的更多相关文章

  1. [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 ...

  2. [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 ...

  3. 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 ...

  4. [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 ...

  5. 【leetcode】Intersection of Two Linked Lists

    题目简述: Write a program to find the node at which the intersection of two singly linked lists begins. ...

  6. 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 ...

  7. 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 ...

  8. ✡ 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 ...

  9. 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 ...

随机推荐

  1. 大数据之ETL设计详解

    ETL是BI项目最重要的一个环节,通常情况下ETL会花掉整个项目的1/3的时间,ETL设计的好坏直接关接到BI项目的成败.ETL也是一个长期的过程,只有不断的发现问题并解决问题,才能使ETL运行效率更 ...

  2. error adding symbols: DSO missing from command line collect2: error: ld returned 1 exit status

    Windows服务器Azure云编译安装MariaDB教程 www.111cn.net 编辑:future 来源:转载 安装MariaDB数据库最多用于linux系统中了,下文给各位介绍在Window ...

  3. MVC(Model(模型) View(视图) Controller(控制器))

    复习 1.      商品表 增删改查 index.php  add.php   view.php   edit.php   action.php 2.      MVC(Model(模型)  Vie ...

  4. Django authentication 使用方法

    转自 : https://docs.djangoproject.com/en/1.8/topics/auth/customizing/

  5. 面向侧面的程序设计AOP-------《三》.Net平台AOP技术概览

    本文转载自张逸:晴窗笔记 .Net平台与Java平台相比,由于它至今在服务端仍不具备与unix系统的兼容性,也不具备类似于Java平台下J2EE这样的企业级容器,使得.Net平台在大型的企业级应用上, ...

  6. Recover Rotated Sorted Array

    Given a rotated sorted array, recover it to sorted array in-place. Clarification What is rotated arr ...

  7. Sql Server 深入的探讨锁机制

    一: 当select遇到性能低下的update会怎么样? 1. 还是使用原始的person表,插入6条数据,由于是4000字节,所以两条数据就是一个数据页,如下图: 1 DROP TABLE dbo. ...

  8. 安装tar.bz2文件

    (1) 解包 – tar jxvf softname-10.0.1.tar.gz -C /usr/src/(-C指的是把文件解压到后面的路径下,此处可以不选) – cd /usr/src/softna ...

  9. Java 复制文件的高效方法

    转载自:http://jingyan.baidu.com/article/ff4116259c2d7712e4823780.html 在Java编程中,复制文件的方法有很多,而且经常要用到.我以前一直 ...

  10. 天使之城(codevs 2821)

    2821 天使之城  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题解  查看运行结果     题目描述 Description 天使城有一个火车站,每辆火车 ...