01 题目描述
输入两个单向链表,找两个链表的第一个公共节点(从第一个公共节点之后都是公共节点)。
如链表
![0b1223bbdc5133fd2dfd93ff2e119cdf.png](https://i-blog.csdnimg.cn/blog_migrate/5c64bed372ee5fec6f4fe7ece50d375c.jpeg)
则第一个公共节点是6
02 解法1
暴力解法,从链表1的第一个节点开始循环,在第二个链表中查找是否存在该节点。存在即为公共节点输出。
该解法的时间复杂度O(n^2),空间复杂度是O(1)
03 解法2
我们观察链表发现,从公共节点开始到最后一个节点都是完全相同的。
![24f277b99d1dec881a97bcd276b86093.png](https://i-blog.csdnimg.cn/blog_migrate/cf071fcc6f9ec7346b3f8e97802a3f29.jpeg)
思考什么数据结构可以从后面开始对比。
栈刚好符合这种情况。我们将链表1的节点和链表2的节点分别放入两个辅助栈中。分别从最后一个节点弹出节点值,对比是否是同一个节点。直到两个节点的值不相等,则上一个出栈的节点,就是要找的第一个公共节点。
![d255ff20c4fa9118ba9a9fa1614807a6.png](https://i-blog.csdnimg.cn/blog_migrate/bae7b33fc4e02dad208e6e4d9c13f930.jpeg)
时间复杂度O(n+m) 空间复杂度 o(n+m), n 和 m分别是两个链表的长度。
04 解法3
既然在解法2中我们已经遍历了两个单向链表,那么我们何不记下来两个链表的长度 m,n。如下图 m.length=5, n.length = 4。
![0b1223bbdc5133fd2dfd93ff2e119cdf.png](https://i-blog.csdnimg.cn/blog_migrate/5c64bed372ee5fec6f4fe7ece50d375c.jpeg)
然后再次遍历,让指针在m的链表上先行 1 (m-n)步。n上的指针后出发,让两个对齐。之后边遍历,边对比值,相等即为第一个公共节点。
![96ce50bf4dc88d4d358c31c5c5bbbd35.png](https://i-blog.csdnimg.cn/blog_migrate/cd2280859b5e2aea6866a81a33689184.jpeg)
这样就没有辅助空间了,时间复杂度还是保留在线性范围内o(m+n).
05 代码
第三种解法的代码。
public static ListNode firstCommonNode(ListNode listNodeA, ListNode listNodeB){ if (listNodeA == null || listNodeB == null) { return null; } int listNodeACount = 0; ListNode countANode = listNodeA; while (countANode != null) { listNodeACount ++; countANode = countANode.next; } int listNodeBCount = 0; ListNode countBNode = listNodeB; while (countBNode != null) { listNodeBCount ++; countBNode = countBNode.next; } int diff = Math.abs(listNodeACount - listNodeBCount); if (listNodeACount >= listNodeBCount) { while (diff > 0) { listNodeA = listNodeA.next; diff --; } } else { while (diff > 0) { listNodeB = listNodeB.next; diff --; } } while (listNodeA != listNodeB && listNodeA != null) { listNodeA = listNodeA.next; listNodeB = listNodeB.next; } return listNodeA;}class ListNode { int value ; ListNode next; public ListNode () { } public ListNode(int value) { this.value = value; } public ListNode(int value, ListNode next) { this.value = value; this.next = next; }}
测试用例
1.没有公共节点。
2.公共节点在第一个,公共节点在中间或者最后一个
3.链表一或者链表二为空。