《剑指Offer》Java刷题 NO.36 两个链表的第一个公共结点(链表,等长拼接法,长者先行法,辅助栈)

传送门:《剑指Offer刷题总目录》

时间:2020-06-19
题目描述

输入两个链表,找出它们的第一个公共结点。(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的)


思路:
这道题针对的是y型链表:第一个公共节点后面都是公共节点
法一: 先遍历两个链表找出两个链表的长度,计算出长度差k,让长链表先走k步,然后两个一起走,直到走到尾部或者两个链表指针对应的节点相同
时间复杂度:O(3n)=O(n)
法二:等长链表法, 两个链表一起遍历,A走到尾部之后继续从B的头部走,B走到尾部之后继续从A的头部走,也就是构造成了两个等长链表,那么最后一定能同时遍历到第一个公共节点:
从下面的分析可以看出,虽然绿色的1相等,但只是两个节点的值(val)相等,并不是同一个节点,后面的8才是同一个节点,才满足 "=="

A:4-1-8-4-5-5-0-1-8-4-5
B:5-0-1-8-4-5-4-1-8-4-5
如果没有公共节点,那么两个链表最后会一起走到终点,都为null
时间复杂度:O(n+m)
法三:利用辅助空间:栈,将两个链表数据分别压栈,依次出栈并比较栈顶元素,最后一对相等的栈顶元素就是第一个公共节点。
时间复杂度:O(n),空间复杂度O(n)


Java代码:

import java.util.Stack;/*** @author LiMin* @Title: FindFirstCommonNode* @Description: 输入两个链表,找出它们的第一个公共结点。(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的)* @date 2020/6/1921:13*/
class ListNode {int val;ListNode next = null;ListNode(int val) {this.val = val;}
}public class FindFirstCommonNode {public static void main(String[] args) {ListNode Node1 = new ListNode(1);ListNode Node2 = new ListNode(2);ListNode Node3 = new ListNode(3);ListNode Node4 = new ListNode(4);ListNode Node5 = new ListNode(5);ListNode Node6 = new ListNode(6);ListNode Node7 = new ListNode(7);ListNode Node8 = new ListNode(8);Node1.next = Node2;Node2.next = Node3;Node3.next = Node6;Node4.next = Node5;//Node5.next = Node6;//Node6.next = Node7;//Node7.next = Node8;FindFirstCommonNode findFirstCommonNode = new FindFirstCommonNode();System.out.println(findFirstCommonNode.findFirstCommonNodeThree(Node1, Node4).val);}/*** 先遍历两个链表找出两个链表的长度,计算出长度差k,让长链表先走k步,然后两个一起走,直到走到尾部或者两个链表指针对应的节点相同*/public ListNode findFirstCommonNodeOne(ListNode pHead1, ListNode pHead2) {if (pHead1 == null || pHead2 == null) return null;if (pHead1 == pHead2) return pHead1;ListNode pLong = pHead1;ListNode pShort = pHead2;//先算出两个链表的长度int length1 = 0;int length2 = 0;while (pLong.next != null) {pLong = pLong.next;length1++;}while (pShort.next != null) {pShort = pShort.next;length2++;}//计算出差值int k = 0;if (length1 > length2) {k = length1 - length2;pLong = pHead1;pShort = pHead2;} else {k = length2 - length1;pLong = pHead2;pShort = pHead1;}//长的先走k步while (k-- > 0) {pLong = pLong.next;}//一起走找公共节点//这里不能写成pLong.next!=null&&pShort.next!=null,当只有一个公共节点时,公共节点的next==null,就会直接跳出while返回nullwhile (pLong != null && pShort != null) {if (pLong == pShort) return pLong;pLong = pLong.next;pShort = pShort.next;}return null;}/*** 等长链表法,两个链表一起遍历,A走到尾部之后继续从B的头部走,B走到尾部之后继续从A的头部走,也就是构造成了两个等长链表,那么最后一定能同时遍历到第一个公共节点*/public ListNode findFirstCommonNodeTwo(ListNode pHead1, ListNode pHead2) {if (pHead1 == null || pHead2 == null) return null;if (pHead1 == pHead2) return pHead1;ListNode p1 = pHead1;ListNode p2 = pHead2;//两种写法,里面有坑while (p1 != p2) {p1 = (p1 == null ? pHead2 : p1.next);p2 = (p2 == null ? pHead1 : p2.next);//不能写成  p1 = (p1.next==null ? pHead2 : p1.next);p2 = (p2.next==null ? pHead1 : p2.next);//当两个链表没有公共节点时,本来应该是p1和p2都等于null时退出while,但这种写法p1和p2取不到null就已经接上下一个头了,所以会有死循环}//        while(p1!=p2){//            p1 = p1.next;
//            p2 = p2.next;
//            if(p1 != p2){//                if(p1 == null)p1 = pHead2;
//                if(p2 == null)p2 = pHead1;
//            }
//        }return p1;}/*** 利用辅助空间:栈,将两个链表数据分别压栈,依次出栈并比较栈顶元素,最后一对相等的栈顶元素就是第一个公共节点。*/public ListNode findFirstCommonNodeThree(ListNode pHead1, ListNode pHead2) {if (pHead1 == null || pHead2 == null) return null;if (pHead1 == pHead2) return pHead1;Stack<ListNode> stack1 = new Stack<>();Stack<ListNode> stack2 = new Stack<>();while (pHead1 != null) {stack1.push(pHead1);pHead1 = pHead1.next;}while (pHead2 != null) {stack2.push(pHead2);pHead2 = pHead2.next;}ListNode result = null;//有相同的元素就更新result,然后一直同时pop,直到当前对应元素不相同,那么上一个被记录的相同元素就是我们要的结果//若第一个元素就不相同就会返回result的初始值:nullwhile (!stack1.empty() && !stack2.empty()) {if (stack1.peek() == stack2.peek()) {result = stack1.pop();stack2.pop();} else return result;}return result;}
}

《剑指Offer》Java刷题 NO.36 两个链表的第一个公共结点(链表,等长拼接法,长者先行法,辅助栈)相关推荐

  1. 《剑指offer》刷题——【链表】从尾到头打印链表

    <剑指offer>刷题--[链表]-<从尾到头打印链表> 问题分析: 递归实现: 1. 无返回值 2. 有返回值(ArrayList) 问题分析: 从头到尾打印链表比较简单,那 ...

  2. 《剑指offer》刷题笔记(发散思维能力):求1+2+3+...+n

    <剑指offer>刷题笔记(发散思维能力):求1+2+3+-+n 转载请注明作者和出处:http://blog.csdn.net/u011475210 代码地址:https://githu ...

  3. 《剑指Offer》刷题之最小的K个数

    <剑指Offer>刷题之最小的K个数 我不知道将去向何方,但我已在路上! 时光匆匆,虽未曾谋面,却相遇于斯,实在是莫大的缘分,感谢您的到访 ! 题目: 给定一个数组,找出其中最小的K个数. ...

  4. 《剑指offer》刷题总结

    从三月初开始刷剑指offer上面的题,到现在花了近二十天的时间终于刷完了.应该说,掌握上面的技巧应付一些公司面试题和小公司的笔试题是完全没有问题的.之前参加一个公司笔试,算法题就有一题是剑指offer ...

  5. 《剑指offer》第九题(用两个栈实现队列)

    // 面试题:用两个栈实现队列 // 题目:用两个栈实现一个队列.队列的声明如下,请实现它的两个函数appendTail // 和deleteHead,分别完成在队列尾部插入结点和在队列头部删除结点的 ...

  6. 挑战一天(12h)刷完《剑指offer》67题

    提前说明,挑战的人不是我. 大家周末好,我是爱上 B 站的小吴,最近一段时间我在网站 AlgoMooc 录制剑指 Offer 的视频,同时上传了一部分到 B 站,基于推荐算法,B 站疯狂的给我推送如何 ...

  7. 《剑指offer》75题 C++详细题解

    目录 简单: 剑指 Offer 03. 数组中重复的数字 map: unordered_map: 原地交换 剑指 Offer 05. 替换空格 剑指 Offer 06. 从尾到头打印链表 出栈入栈 双 ...

  8. 剑指offer第41题 和为s的两个数

    剑指offer第41题 和为s的两个数 #include<iostream> using namespace std;bool sumk(int*list,int length,int*n ...

  9. 剑指offer java版 test3—从尾到头打印链表

    标题:剑指offer java版 test3-从尾到头打印链表 题目:输入一个链表,按链表从尾到头的顺序返回一个ArrayList. 解答:知识不够全面,用ArrayList做的 但是看到大佬们还可以 ...

最新文章

  1. JS 中 URL 编码的问题.
  2. python pywin32 微信_python win32con安装_python-2.7 – 安装pywin32
  3. CentOS7使用阿里云镜像安装Mongodb
  4. setTimeout() 方法的返回值
  5. 技术干货 | iOS 高阶容器详解
  6. mycat两个mysql实例的搭建_Mycat-多实例的搭建
  7. c语言中const的作用面试,C语言const关键字作用
  8. 下载所有需要的rpm文件路径
  9. vue 解决跨域 调试_vue+Java后端进行调试时解决跨域问题的方式
  10. python ssh模块_python ssh之paramiko模块使用
  11. 获取本地文件所需配置
  12. iOS打包后收不到推送信息
  13. Linux 如何对http服务器进行压力测试
  14. 简析选购电磁流量计的四大考虑因素
  15. android 放大镜功能,Android放大镜效果实现
  16. LL(1)语法分析实验报告
  17. 消费信贷评分建模与应用笔记-2
  18. 淘宝/天猫API,获得淘宝商品评论返回值说明(数据解析)
  19. 怎样在证件照片底部加文字
  20. 左耳听风ARTS第1周

热门文章

  1. html从入门到精通前锋,战术干货 | 从入门到精通,支点中锋-锋线球员搭配个人向深度解析!下篇...
  2. 什么是I2C,I2C怎么用,从实例波形分析I2C读写
  3. linux基础操作练习题
  4. Chapter 4、JDK 动态代理
  5. Joinquant : 不限语言·极速调取 | JQData HTTP 接口正式上线
  6. 模块之间的耦合性到底指的是什么,js如何减少耦合性
  7. 下述代码每句函数都表达什么意思,可以详细解析下马?template typename PointT, typename Dist int pcl::KdTreeFLANNPointT, Dis...
  8. 马踏棋盘问题的程序c语言,请各位C语言大神解释下马踏棋盘的程序,各模块功能,原理,方法,如? 爱问知识人...
  9. HTML+CSS+JavaScript入门教程(万字)
  10. verilog 8位全加器