两个单链表相交的一系列问题

【题目】

在本题中,单链表可能有环,也可能无环。给定两个单链表的头节点 head1和head2,这两个链表可能相交,也可能不相交。请实现一个函数, 如果两个链表相交,请返回相交的第一个节点;如果不相交,返回null 即可。 要求:如果链表1的长度为N,链表2的长度为M,时间复杂度请达到 O(N+M),额外空间复杂度请达到O(1)

【思路】

我们可以把本题分解成三个问题

  • 链表是否有环

    • 解法一:利用哈希表解决问题

      从第一个节点开始,如果哈希表中不存在,则把节点插入到哈希表中,如果存在的话,则此节点就是最后所求的节点。

    • 解法二:不用哈希表解决问题(这是一个数学问题)

      用两个指针,一个快指针,一个慢指针同时从单链表头部开始遍历,一快一慢:

      若无环,肯定快指针先遍历到null,此时单链表无环.

      若单链表有环,这两个指针肯定在环中相遇,相遇时,让快指针从头head开始遍历,然后放慢速度跟慢指针一样快,两个继续同时向下遍历,直到相遇,此时就是单链表入环节点。

  • 两个链表是否相交,相交的第一个节点是在什么位置

    • 两个无环单链表是否相交

      • 解法一:利用哈希表解决问题

        1.把链表一中所有的节点放到哈希表中

        2.遍历第二个链表,每个元素在map中是否存在,第一个存在的节点即为相交的第一个节点,如果到达最后都没有的话,及两个链表中不存在链表。

      • 解法二:不利用哈希表解决问题

        1.统计链表一,去统计链表一的长度和及链表一的最后一个节点。统计链表二,去统计链表二的长度和及链表二的最后一个节点。

        2.去比较两个链表的最后一个节点是否相等(比较内存地址),如果内存地址相同,则两个链表必然相交,如果两个链表最后节点的地址不相等,则两个链表必定不相交。

        ​ 2.1 如果两个链表尾节点相交的话,我们可以确定两个链表相交,但是不能确定第一个相交的节点,那我们又应该如何去得到两个链表的第一个节点的位置呢:

        ​ 2.2 比较两个链表的长度,让长度长的链表先走长度差的步数,然后去两个链表同时去走一步,去比较两个链表的每个节点,第一个形同的节点及为所求的第一个相交的节点

    • 一个链表有环,另一个链表无环

      两个量链表不可能相交

    • 两个链表有环的链表

公共前提:

  • 共三种情况

loop1和loop2 的内存地址不同,loop1的一直next的过程中都转回自己了,还没有遇到loop2

loop1和loop2 的内存地址不同,loop1的一直next的过程中与loop2的地址内存相等了,返回loop1也好或者返回loop2也行,都对。

如果loop1和loop2的内存位置相同

【代码实现】

#include <iostream>
#include<stdlib.h>using namespace std;class Node
{public:Node(int data){value = data;next = NULL;}
public:int value;Node *next;
};//鎵惧埌鍏ョ幆鑺傜偣
Node* getLoopNode(Node *head)
{if(NULL == head || NULL == head->next || NULL == head->next->next)return NULL;Node *n1 = head->next;Node *n2 = head->next->next;while(n1 != n2){if(NULL == n2->next || NULL == n2->next->next)return NULL;n2 = n2->next->next;n1 = n1->next;}n2 = head;while(n1 != n2){n1 = n1->next;n2 = n2->next;}return n1;
}//涓嶅甫鐜殑閾捐〃鐨勭浉浜よ妭鐐?
Node* noLoop(Node *head1,Node *head2)
{if(NULL == head1 || NULL == head2)return NULL;Node *cur1 = head1;Node *cur2 = head2;int n = 0;while(NULL != cur1->next){n++;cur1 = cur1->next;}while(NULL != cur2->next){n--;cur2 = cur2->next;}if(cur1 != cur2)    //鑻ユ渶鍚庝竴涓妭鐐逛笉鎯崇瓑锛屽垯淇╅摼琛ㄤ笉鐩镐氦return NULL;cur1 = n > 0 ? head1 : head2;cur2 = cur1 == head1 ? head2 : head1;n = abs(n);while(0 != n)  //浠ヨ緝鐭殑閭d釜閾捐〃涓哄噯{n--;cur1 = cur1->next;}while(cur1 != cur2){cur1 = cur1->next;cur2 = cur2->next;}return cur1;
}//甯︾幆閾捐〃鐨勭浉浜よ妭鐐圭殑鍒ゆ柇
Node* bothLoop(Node *head1,Node *loop1,Node *head2,Node *loop2)
{Node *cur1(NULL),*cur2(NULL);if(loop1 == loop2)    //涓庝笉甯︾幆鐨勭浉浜よ妭鐐圭殑鍒ゆ柇涓€鏍风殑{cur1 = head1;cur2 = head2;int n = 0;while(cur1 != loop1){n++;cur1 = cur1->next;}while(cur2 != loop2){n--;cur2 = cur2->next;}cur1 = n > 0 ? head1 : head2;cur2 = cur1 == head1 ? head2 : head1;n = abs(n);while(0 != n){n--;cur1 = cur1->next;}while(cur1 != cur2){cur1 = cur1->next;cur2 = cur2->next;}return cur1;}else{cur1 = loop1->next;while(cur1 != loop1){if(cur1 == loop2)return loop2;cur1 = cur1->next;}return NULL;}
}Node* getIntersectNode(Node *head1,Node *head2)
{if(NULL == head1 || NULL == head2)return NULL;Node *loop1 = getLoopNode(head1);Node *loop2 = getLoopNode(head2);if(NULL == loop1 && NULL == loop2)return noLoop(head1,head2);if(NULL != loop1 && NULL != loop2)return bothLoop(head1,loop1,head2,loop2);return NULL;
}int main()
{Node *head1 = NULL;Node *head2 = NULL;Node *ptr1 = NULL;Node *ptr2 = NULL;Node *head3 = NULL;Node *ptr3 = NULL;for(int i =0;i<4;i++)//鏋勯€犻摼琛?{if(NULL == head1 || NULL == head2){    head1 = new Node(i);head1->next = NULL;ptr1 = head1;head2 = new Node(i);head2->next = NULL;ptr2 = head2;head3 = new Node(10-i);head3->next = NULL;ptr3 = head3;continue;}ptr1->next = new Node(i);ptr1 = ptr1->next;ptr1->next = NULL;ptr2->next = new Node(i);ptr2 = ptr2->next;ptr2->next = NULL;ptr3->next = new Node(10-i);ptr3 = ptr3->next;ptr3->next = NULL;}//绗竴锛氭棤鐜笉鐩镐氦if(NULL == getIntersectNode(head1,head2))cout << "Two lists are not intersecting!" << endl;//绗簩锛氭湁鐜笉鐩镐氦ptr1->next = head1->next;ptr2->next = head2->next;if(NULL == getIntersectNode(head1,head2))cout << "Two lists are not intersecting!" << endl;    //绗笁锛氭棤鐜浉浜?ptr1->next = head3;ptr2->next = head3;if(NULL != getIntersectNode(head1,head2))cout << "Two lists are intersecting!" << getIntersectNode(head1,head2)->value << endl;//绗洓鏈夌幆鐩镐氦ptr3->next = head3;if(NULL != getIntersectNode(head1,head2))cout << "Two lists are intersecting!" << getIntersectNode(head1,head2)->value << endl;return 0;
}

算法学习18-两个单链表相交的一系列问题相关推荐

  1. 左神算法:两个单链表相交的一系列问题(链表是否有环 / 两无环链表是否相交 / 两有环链表是否相交)

    本题来自左神<程序员代码面试指南>"两个单链表相交的一系列问题"题目. 题目 在本题中,单链表可能有环,也可能无环.给定两个单链表的头节点 head1 和 head2, ...

  2. 两个单链表相交的一系列问题-Java

    分享一个大牛的人工智能教程.零基础!通俗易懂!风趣幽默!希望你也加入到人工智能的队伍中来!请轻击http://www.captainbed.net package live.every.day.Pro ...

  3. 两个单链表相交的一系列问题

    两个单链表相交的一系列问题 在本题中,单链表可能有环,也可能无环.给定两个单链表的头节点 head1 和 head2,这两个链表可能相交,也可能 不相交.请实现一个函数,如果两个链表相交,请返回相交的 ...

  4. 两个单链表相交的一系列问题----0_0

    这道题emmm,难度相对来说很大额. 主要是要分成三种情况来考虑: 1. 两个链表都无环: 2. 两个链表都有环: 3. 一个有环一个无环,这种情况是不用 考虑的,一定没有交点(姥姥记住:单链表仅有一 ...

  5. 算法题:求两个单链表相交的第一个节点

    目录 一.题目 思路 代码 二.总结 一.题目 #include <iostream> #include <stack> using namespace std; //链表结点 ...

  6. 链表问题11——两个单链表相交的系列问题(四):总结

    题目 请实现一个函数,如果两个链表相交,请返回相交的第一个节点,如果不相交,返回null即可.链表可能有环或无环. 要求 如果链表1的长度为N,链表2的长度为M,时间复杂度达到O(M+N),额外空间复 ...

  7. 链表问题11——两个单链表相交的系列问题(三):判断两个有环链表是否相交

    题目 判断两个有环链表是否相交,相交则返回第一个相交节点,否则返回null 在考虑此问题时,根据前面几篇文章的解法,我们已经得到了各自链表的入环节点,分别为loop1和loop2 思路 以下是问题三的 ...

  8. 链表问题11——两个单链表相交的系列问题(二):找到两个无环链表的交点

    题目 判断两个无环链表是否相交,相交则返回第一个相交节点,否则返回null 思路 分别遍历链表1和链表2,最后一个节点分别即为end1和end2,长度分别记为len1和len2 如果end1不等于en ...

  9. 链表问题11——两个单链表相交的系列问题(一):找到有环链表的环入口节点

    题目 判断一个链表是否有环,如果有,则返回第一个进入环的节点,没有则返回null. 思路 如果一个链表没有环,那么遍历链表一定可以遇到链表的终点:如果链表有环,那么遍历链表就永远在环里转下去了.如何找 ...

最新文章

  1. linux mysql内网_在Linux中mysql的一些基本操作
  2. 【Homework】什么是多态,多态具体体现有哪些?
  3. Samba将Linux集成到Windows网络
  4. 科大讯飞 ai算法挑战赛_为井字游戏挑战构建AI算法
  5. python中pop函数的用法_python中pop()函数怎么用
  6. scrapy FormRequest
  7. JQuery的$.extend()的源码
  8. PDF Expert 坚果云 强强联合 优惠来袭
  9. Contest-hunter 暑假送温暖 SRM08
  10. STM32RTC唤醒功能配置(基于LL库)
  11. MAC 安装 kafka
  12. 嵌入式linux模块复位,嵌入式linux下复位声卡驱动
  13. 软件测试题目 如何测一个三角形,软件测试三角形问题(覆盖测试)
  14. 北京地铁月度消费总金额计算(Python版)
  15. Android开发新手入门总结(1)
  16. 周期函数的自身叠加后功率函数思考
  17. css:html元素的定位
  18. FCKeditor 介绍
  19. 一张图认识Python(附基本语法总结)
  20. ajax和axios封装

热门文章

  1. [循证理论与实践] Meta分析系列之五:贝叶斯 Meta 分析与 WinBUGS 软件
  2. java内存分析工具_java内存查看与分析
  3. P3437 [POI2006]TET-Tetris 3D
  4. 6个炒菜习惯 丢失营养
  5. 2022年总结:道阻且长,行则将至
  6. 2019杭电多校第三场 6608 Fansblog(威尔逊定理+miller_rabin素性测试)
  7. python——pycharm使用入门
  8. 彗星撞地球 | 近25万倍压缩的精品3D动画
  9. linux 命令例子
  10. IPad 如何使用蓝牙鼠标