找到两个链表的合并点
[!Tip]
本节源代码见Github链接🔗
问题描述
假设两个单向链表在某个结点相交后,成为一个单向链表。两个链表的表头结点是已知的,但是相交的结点未知。设计算法找到两个链表的合并点
核心思路
通过双指针解决。先将两个指针移动到距离合并点相同距离的位置(如上图分别是1和3),然后同时移动两个指针,两个指针相遇点即合并点。主要包含以下3步:
- 分别计算两个链表的长度;
- 两个链表的长度差值,即长链表指针需要向前移动的距离,如上图中长链表指针需要向前移动1个结点;
- 按相同速度同时移动两个指针,指针相遇点即合并点。
实现代码
【👉🏻>>点击展开查看代码】
/**
* 找到两个单向链表的合并点
*
* @param firstHeadNode 第一个链表的表头指针
* @param secondHeadNode 第二个链表的表头指针
* @return NormalListNode
* @author: Max Solider
* @date: 2022/10/9 14:18
*/
NormalListNode findIntersectingNode(NormalListNode firstHeadNode, NormalListNode secondHeadNode) {
if (firstHeadNode == null || secondHeadNode == null) {
return null;
}
// 计算两个链表的长度
int firstLength = getListLength(firstHeadNode);
int secondLength = getListLength(secondHeadNode);
// 计算两个链表的长度差值
NormalListNode longerNode = null;
NormalListNode shorterNode = null;
int diffLength = 0;
if (firstLength > secondLength) {
longerNode = firstHeadNode;
shorterNode = secondHeadNode;
diffLength = firstLength - secondLength;
} else {
longerNode = secondHeadNode;
shorterNode = firstHeadNode;
diffLength = secondLength - firstLength;
}
// 将指向更长链表的指针向前移动,直到两个指针距离合并点的距离相同
while (diffLength > 0) {
longerNode = longerNode.getNext();
diffLength--;
}
// 两个指针同时移动,相遇点即合并点。若没相遇则说明没有合并
while (longerNode != null) {
if (longerNode == shorterNode) {
System.out.println("The merging point of two linked lists is " + longerNode.getData());
return longerNode;
}
longerNode = longerNode.getNext();
shorterNode = shorterNode.getNext();
}
System.out.println("The is no merging point of two linked lists.");
return null;
}
/**
* 计算链表长度
*
* @param headNode 链表头指针
* @return int 链表长度
* @author: Max Solider
* @date: 2022/10/9 16:36
*/
int getListLength(NormalListNode headNode) {
if (headNode == null) {
return 0;
}
int count = 0;
NormalListNode node = headNode;
while (node != null) {
node = node.getNext();
count++;
}
return count;
}
时间复杂度
时间复杂度为O(max(n,m)),用于遍历链表。
空间复杂度
空间复杂度为O(1),用于存储临时变量。