最近听了左神的算法课,对一些常用数据结构以及算法改进的思路有了更深的理解,特此总结,不定期更新算法题目以及答案总结!笔者使用C++进行算法重现!虽然左神使用的是JAVA,但他自己也说了,算法与语言无关,但C++写出来的复杂度过不了,那么用其他的语言JAVA,Python也一定过不了!所以刷题还是尽量C++吧,算法基本用不了什么库函数,顶多几个数据结构,而C++的STL里面都包含。

单向链表

首先什么是单向链表,其实质也很简单,也就是有一个自定义的节点,其内部有且只有一个指针指向下一节点。但是一定要注意,单向链表分为单向有环链表和单向无环链表,其中单向无环链表的末节点为null。所以在面试时一定要注意题目的单向链表有没有说有环还是无环!

题目:两个单链表相交的第一个节点

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

首先我们先画出链表相交的几种形式,如下图所有,共有四种情况:

  1. 两个无环单向链表相交
  2. 两个有环单向链表相交,但入环节点不在同一个节点
  3. 两个有环单向链表相交,但入环节点为同一个节点
  4. 两个单向链表不相交
  5. 注意,情况四不是单向链表结构,其中间节点内部必有两个指针

我们分析好了之后,开始Coding......

首先建立一个函数,判断一个单向链表是否有环,如果有则返回入环节点,如果没有返回null.在这里使用快慢指针的方法:(也可以使用set,但需要辅助空间)

  1. 快指针走两步, 满指针走一步,如果有环则两者必在一个节点重合
  2. 重合以后,快指针回到原来出发节点,改为步长为1
  3. 快慢指针再次走(步长为1),重合节点即为目标节点

如果不信,可以自己试试,数学能力好的可以自己证明!

// 如果没有环返回null, 如果有环返回入环的第一个节点(快慢指针的方式)

接着,经过上面的函数后,我们会得到两种情况:有环链表相交和无环链表相交!但有人问,可不可以一个有环和一个无环相交?绝对不可能,这是单向链表!!!

并且,经过分析后,发现有环链表相交的情况为两种(情况二和情况三),而无环链表相交的情况只有Y字型一种(情况一)。

两个无环链表相交

这个就很简单了,也就是我画的情况一,Y字型,首先遍历两个链表,得出两个链表的长度差n,然后让长链表先遍历n个节点,接着两个链表同时遍历,直到节点相同,则相同节点为目标节点。一定要注意长度差的计算,并且如何区分长短链表!

那么怎么判断不相交呢?对于无环链表来说,相交的情况只存在Y字型,因此只要比对最后节点是不是相同就可以了,因为无环相交的最后一个节点必定相同!

Node* noLoop(Node* head1, Node* head2){   // 只能是Y字型结构if (head1 == nullptr || head2 == nullptr){return nullptr;}Node* cur1 = head1;Node* cur2 = head2;int len1 = 0, len2 = 0;while(cur1->next != nullptr){len1++;cur1 = cur1->next;}while(cur2->next != nullptr){len2++;cur2 = cur2->next;}if(cur1 != cur2){    // 如果有公共部分,必定指向统一节点return nullptr;}int n = len1 - len2;   cur1 = (n > 0) ? head1 : head2;             // cur1为较长的listcur2 = cur1 == head1 ? head2 : head1;       // cur2为较短的listn = n < 0 ? -1*n : n;  // 取绝对值while(n != 0){n --;cur1 = cur1->next;} while(cur1 != cur2){cur1 = cur1->next;cur2 = cur2->next;}return cur1;
}

两个有环链表相交

有环链表相交分为两种情况,即图中的情况二和情况三,也就是入环节点在不在同一个节点?

  1. 入环节点在同一个节点:那么查找第一个相交节点的方法就和无环链表相交节点的查询方式一样了,只不过是终止点由null变成了loop(入环节点)
  2. 入环节点不在同一个节点:那么就从第一个入环节点loop1开始遍历,如果遇到了第二个入环节点loop2,那么说明第一个节点为目标节点,如果没有遇到,那说明这两个链表都是有环单向链表,但是不相交!返回null。
Node* bothLoop(Node* head1, Node* loop1, Node* head2, Node* loop2){Node* cur1 = nullptr;Node* cur2 = nullptr;if(loop1 == loop2){     // Y型下面有一个环,和Y型类似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 = n < 0 ? -1*n : n;while(n != 0){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 loop1;     // 天线宝宝型的拓扑结构}cur1 = cur1->next;}return nullptr;           // 两个有环链表不相交}
}

由于C++中new出来的节点,需要进行delete进行内存释放,但笔者在测试文件中只写了单向无环链表的内存释放函数,而有环的如何释放笔者也有点迷茫,有大佬知道的还请告知一下!

完整测试文件(C++版),文件名为:两个单向链表(有环无环)第一个相交节点。请关注我的个人公众号 (算法工程师之路),回复"左神算法基础CPP"即可获得,并实时更新!希望大家多多支持哦~

公众号简介:分享算法工程师必备技能,谈谈那些有深度有意思的算法,主要范围:C++数据结构与算法/深度学习(CV),立志成为Offer收割机!坚持分享算法题目和解题思路(Day By Day)

算法工程师之路

neo4j 查询同一节点的两个上级_链表的魅力:两个单向链表的第一个交点相关推荐

  1. java合并两个数组_「JAVA」两个数组的交集—力扣每日一题(一)

    示例 1: 输入: nums1 = [1,2,2,1], nums2 = [2,2] 输出: [2,2] 示例 2: 输入: nums1 = [4,9,5], nums2 = [9,4,9,8,4] ...

  2. 未能比较数组中的两个元素_算法3 寻找两个正序数组的中序数

    问题描述: 给定两个大小为 m 和 n 的正序(从小到大)数组 nums1 和 nums2.请你找出并返回这两个正序数组的中位数.要求设计一个时间复杂度为 O(log (m+n)) 的算法解决此问题. ...

  3. neo4j 查询同一节点的两个上级_手把手教你快速入门知识图谱 - Neo4J教程

    前言 今天,我们来聊一聊知识图谱中的Neo4J.首先,什么是知识图谱?先摘一段百度百科: 知识图谱(Knowledge Graph),在图书情报界称为知识域可视化或知识领域映射地图,是显示知识发展进程 ...

  4. neo4j 查询同一节点的两个上级_如何用Neo4j和ScikitLearn做机器学习任务?| 附超详细分步教程...

    作者 | Mark Needham译者 | Tianyu.Shawnice编辑 | Jane出品 | AI科技大本营(ID:rgznai100)图算法不是一个新兴技术领域,在开源库中已经有很多功能强大 ...

  5. neo4j 查询同一节点的两个上级_WhatRoute for Mac(互联网流量诊断查询工具)

    如果您想在不使用命令行的情况下执行流量诊断查询,那么WhatRoute是一个不错的选择.WhatRoute提供了一个干净且有条理的界面,主要提供Traceroute功能,但也可以执行Ping,域名服务 ...

  6. python一个图画两条曲线_用python建立两个Y轴的XY曲线图方法

    想把python提取出来的 加载点反力和某个单元的应力画在同一个XY曲线图上,由于两者数量级差太远,故而需要建立有两个Y轴的XY曲线图. 效果为: 代码如下: #创建Quatype,作为标记,用于判断 ...

  7. 电脑开两个微信_电脑怎么登录两个微信

    1/4 下载并安装微信电脑客户端,保证这台电脑没有登陆微信 2/4 就像正常打开微信一样,不过不是双击,而是快速连点四次 3/4 我们可以看到有两个微信登陆界面 4/4 用两个不同的账号进行扫码登陆即 ...

  8. 用spss做多组两两相关性分析_卡方检验的事后两两比较

    卡方检验检出组间差异后,得到的结果只能显示行变量与列变量间是否相互独立,但各变量的不同组别间具体存在何种差异呢?这需要后续通过两两比较来得到更为精确的结论.下面,我将用一个简单的案例向大家演示:在SP ...

  9. python求两数最大公因数_使用辗转相除法求两个数的最大公因数(python实现)

    数学背景: 整除的定义: 任给两个整数a,b,其中b≠0,如果存在一个整数q使得等式 a = bq 成立,我们就说是b整除a,记做b|a. 性质1:如果c|a,c|b,且对于任意的整数m,n,则有c| ...

最新文章

  1. uni-app在iOS移动端页面上下滑动关闭(页面回弹问题,非刷新)
  2. 数字图像处理实验(10):PROJECT 05-01 [Multiple Uses],Noise Generators
  3. Spring Boot——控制台LOGO自定义配置管理解决方案
  4. 《零基础看得懂的C++入门教程 》——(2)什么是数据类型、变量?一看便会
  5. java jstack 死锁_利用jstack检测死锁DeadLock
  6. UIControl事件
  7. 读取页面上所有的checkbox
  8. [转]《编程之道》(很老的一篇文章)
  9. 2020-11-12杂谈
  10. Splunk中12小时制AM/PM的日期转换
  11. php代码审计靶场,RIPS --代码审计靶场(第一关)-华盟网
  12. 2021年如何通过网络赚钱
  13. Handling Complexity in the Halo 2 AI
  14. jQuery读取JSON数据(jQuery调用JSON数据学习第二天)
  15. jqury ajax 标准
  16. DNUICTF反思总结
  17. html如何让图片不失真,图片放大不失真的几种方法
  18. 不同版本iOS的特性和差异
  19. ps——拼接两张图片
  20. Blog3 无监督深度关键短语生成——关键代码分析1

热门文章

  1. 不使用手机代理,进行手机抓包
  2. 损失函数与代价函数区别
  3. Android Studio 工具窗口浮动与布局恢复【申明:来源于网络】
  4. DOM、Window操作
  5. 友盟ionic多渠道自动签名app
  6. [转]JSP中常见的Tomcat报错错误解析(一)
  7. 金融系列5《AUTH过程》
  8. rtmp rtsp 区别_鱼胶粉和吉利丁粉的区别
  9. win10企业版永久关闭自动更新
  10. windows下release模式调试某行代码无法中断