剑指offer 学习笔记 两个链表的第一个公共节点
面试题52:两个链表的第一个公共节点。输入两个链表,找出它们的第一个公共节点,链表节点定义如下:
struct ListNode {
int m_nKey;
ListNode* m_pNext;
};
蛮力法:在第一个链表上顺序遍历每个节点,每遍历到一个节点,就在第二个链表上顺序遍历每个节点,直到找到第一个公共节点,如果第一个链表长为m,第二个链表长度为n,那么时间复杂度为O(mn),太慢了。
法二:我们可以把两个链表分别放到两个栈中,而栈顶元素一定是一样的,因为最后一个元素一定是公共的节点,接着从两个栈中出栈一个元素,再比较栈顶元素,直到两个栈顶元素不同,那么上次出栈的节点即为第一个公共节点。这种方法的时间复杂度为O(m+n),空间复杂度也是O(m+n),与蛮力法相比,时间效率得到了提高,但是以牺牲空间效率为代价。
法三:法二牺牲了空间效率换来了时间性能的提升,也可以先遍历两个链表,从而得到长度,即得到了两链表的长度差,之后长的先遍历长度差个节点,之后两个链表再一起向尾部遍历,直到找到第一个相同的节点。这种方法时间复杂度也是O(m+n),但不需要辅助栈。
以下代码使用下图链表为例:
#include <iostream>
using namespace std;
struct ListNode {
int m_nKey;
ListNode* m_pNext;
};
int GetListLength(ListNode* head) {
ListNode* pNode = head;
int count = 0;
while (pNode != nullptr) {
++count;
pNode = pNode->m_pNext;
}
return count;
}
ListNode* FindFirstCommonNode(ListNode* head1, ListNode* head2) {
if (head1 == nullptr || head2 == nullptr) {
return nullptr;
}
int length1 = GetListLength(head1);
int length2 = GetListLength(head2);
ListNode* longList = head1;
ListNode* shortList = head2;
int lengthDif = length1 - length2;
if (length1 < length2) {
longList = head2;
shortList = head1;
lengthDif = -lengthDif;
}
while (lengthDif > 0) {
longList = longList->m_pNext;
--lengthDif;
}
while (longList != nullptr) {
if (longList == shortList) {
break;
}
longList = longList->m_pNext;
shortList = shortList->m_pNext;
}
return longList;
}
int main() {
ListNode* pNode1 = new ListNode();
ListNode* pNode2 = new ListNode();
ListNode* pNode3 = new ListNode();
ListNode* pNode4 = new ListNode();
ListNode* pNode5 = new ListNode();
ListNode* pNode6 = new ListNode();
ListNode* pNode7 = new ListNode();
pNode1->m_nKey = 1;
pNode2->m_nKey = 2;
pNode3->m_nKey = 3;
pNode4->m_nKey = 4;
pNode5->m_nKey = 5;
pNode6->m_nKey = 6;
pNode7->m_nKey = 7;
pNode1->m_pNext = pNode2;
pNode2->m_pNext = pNode3;
pNode3->m_pNext = pNode6;
pNode4->m_pNext = pNode5;
pNode5->m_pNext = pNode6;
pNode6->m_pNext = pNode7;
pNode7->m_pNext = nullptr;
ListNode* commonNode = FindFirstCommonNode(pNode1, pNode4);
if (commonNode) {
cout << "第一个公共节点值为:" << commonNode->m_nKey << endl;
} else {
cout << "没有公共节点。" << endl;
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)