(剑指Offer)面试题37:两个链表的第一个公共结点
题目:
输入两个链表,找出它们的第一个公共结点。
链表结点的定义如下:
struct ListNode{ int val; ListNode* next; ListNode(int x):val(x),next(NULL){}; };
思路:
1、暴力法
遍历第一个链表,每遍历到一个结点,在第二个链表中顺序遍历,如果在第二个链表上有一个结点和该结点一样,说明两个链表在这个结点上重合,也就是第一个公共结点。
时间复杂度:O(mn)
2、堆栈法
如果两个链表存在公共结点,那么从第一个公共结点到链尾,所有结点都是重合的,如果我们从两个链表的尾部开始往前比较,最后一个相同的结点就是第一个公共结点。
但单链表只有后继指针,不能往回移动,我们可以很快想到了栈,将两个链表的结点分别放入两个栈里,这样两个尾指针都在栈顶,接着下就比较栈顶指针是否相同,如果是,则把栈顶弹出,继续比较下一个栈顶,直至找到最后一个相同的结点。
时间复杂度:O(m+n),空间复杂度:O(m+n)
3、两个指针
首先分别遍历两个链表A,B,得到各自的长度如lenA,lenB,假设lenA>lenB,然后让A指针先走lenA-lenB步,接着两个指针一块走,直至相遇即找到第一个公共结点。
时间复杂度:O(m+n)
代码:
这里只实现方法3
struct ListNode{ int val; ListNode* next; ListNode(int x):val(x),next(NULL){}; }; unsigned int GetListLength(ListNode* pHead){ unsigned int len=0; while(pHead!=NULL){ len++; pHead=pHead->next; } return len; } ListNode* FindFirstCommonNode(ListNode* pHead1,ListNode* pHead2){ unsigned int len1=GetListLength(pHead1); unsigned int len2=GetListLength(pHead2); ListNode* pLong=pHead1; ListNode* pShort=pHead2; unsigned lenDiff=len1-len2; if(len1<len2){ pLong=pHead2; pShort=pHead1; lenDiff=len2-len1; } for(unsigned int i=0;i<lenDiff;i++) pLong=pLong->next; while(pShort!=NULL && pLong!=NULL && pShort!=pLong){ pShort=pShort->next; pLong=pLong->next; } ListNode* pFirstCommonNode=pLong; return pFirstCommonNode; }
在线测试OJ:
http://www.nowcoder.com/books/coding-interviews/6ab1d9a29e88450685099d45c9e31e46?rp=2
AC代码:
/* struct ListNode { int val; struct ListNode *next; ListNode(int x) : val(x), next(NULL) { } };*/ class Solution { public: ListNode* FindFirstCommonNode( ListNode *pHead1, ListNode *pHead2) { int len1=GetListLength(pHead1); int len2=GetListLength(pHead2); ListNode* pLong=pHead1; ListNode* pShort=pHead2; int lenDiff=len1-len2; if(len1<len2){ pLong=pHead2; pShort=pHead1; lenDiff=len2-len1; } for(int i=0;i<lenDiff;i++) pLong=pLong->next; while(pLong!=NULL && pShort!=NULL && pLong!=pShort){ pLong=pLong->next; pShort=pShort->next; } ListNode* pFirstCommonNode=pLong; return pFirstCommonNode; } unsigned int GetListLength(ListNode* pHead){ unsigned int len=0; while(pHead!=NULL){ ++len; pHead=pHead->next; } return len; } };