剑指offer 37:求两个链表的第一个公共节点
2016-03-30 15:07
375 查看
剑指offer 37: 求两个单链表的第一个公共节点
节点定义如下:typedef int ElemType; typedef struct LNode { ElemType data; struct LNode *pNext; }LNode, *LinkList;
蛮力法
在第一个链表上顺序遍历每个节点,每遍历一个节点的时候,在第二个链表上顺序遍历每个节点,判断两节点是否相等。时间复杂度为o(m * n);空间换时间:栈
两个链表如果有公共节点,则公共节点会在表尾。可以从两个链表的尾部开始比较,最后一个相同的节点即为第一个公共节点。然而链表不能反向遍历,因此想到遍历每一个链表,将每个节点入栈,然后依次比较两个栈顶节点。弹出两个栈顶,比较如果相等,则再出栈比较,如果不相等,则为公共节点。此时时间复杂度为o(m + n),空间复杂度为o(m + n);多次遍历链表法
1 遍历两个链表得到长度差n2 让指针在长的链表上先多走n步
3 最后让两个指针同时遍历,直到两者相等,即为第一个公共节点
此时,时间复杂度仍然为o(m + n),但无需辅助栈,提高了空间复杂度。
代码如下
LNode* q37_FindFirstCommonNode(LinkList L1, LinkList L2) { if (nullptr == L1 || nullptr == L2) { return nullptr; } unsigned int len1 = q37_GetListLength(L1); unsigned int len2 = q37_GetListLength(L2); int distance = 0; LNode *pLong = L1; LNode *pShort = L2; //保证distance是正数,且pLong指向长链表,pShort指向短链表 if (len1 > len2) { distance = len1 - len2; } else { distance = len2 - len1; pLong = L2; pShort = L1; } //先让长链表多走几步 while (distance > 0) { pLong = pLong->pNext; distance--; } //同时向后走 while (pLong && pShort && pLong != pShort) { pLong = pLong->pNext; pShort = pShort->pNext; } if (!pLong) {//没有共同节点 return nullptr; } else { return pLong; } } unsigned int q37_GetListLength(LinkList L) { unsigned int len = 0; LNode *p = L; while (p) { ++len; p = p->pNext; } return len; }
总结
链表中,优化时空复杂度:一个思路是多次遍历链表得到更多信息,然后再用已得到信息解题;
另一个思路是设置两个指针,通过设置指针遍历的速度(一个走一步,另一个走两步)或者让一个指针先走多步,然后同时走。
相关文章推荐
- 文件遍历排序函数
- Lua 学习笔记之C API 遍历 Table实现代码
- C#遍历文件夹后上传文件夹中所有文件错误案例分析
- C#中遍历Hashtable的4种方法
- C#定义并实现单链表实例解析
- C#数据结构之单链表(LinkList)实例详解
- Erlang中遍历取出某个位置的最大值代码
- C++实现图的邻接矩阵存储和广度、深度优先遍历实例分析
- C++实现图的邻接表存储和广度优先遍历实例分析
- C语言实现单链表逆序与逆序输出实例
- C++非递归队列实现二叉树的广度优先遍历
- php遍历目录方法小结
- 一个目录遍历函数
- php遍历删除整个目录及文件的方法
- PHP遍历文件夹与文件类及处理类用法实例
- PHP遍历XML文档所有节点的方法
- php中使用key,value,current,next和prev函数遍历数组的方法
- C#使用前序遍历、中序遍历和后序遍历打印二叉树的方法
- C#使用foreach遍历哈希表(hashtable)的方法
- php递归遍历多维数组的方法