版权声明:本文为博主原创文章,欢迎转载,转载请声明出处! https://blog.csdn.net/hansionz/article/details/82717368
题目:输入两条单链表
,求它们的第一个公共结点。结点的定义如下:
typedef struct Node
{
DataType data;
struct Node* next;
}Node,*pLinkList;
解题思路:
方法一:
暴力法。
拿出一条链表中的一个结点,然后在另一条链表中从前向后扫描,如果存在相同的结点,则此节点为第一个公共结点,否则,继续向后遍历。假设两条链表的长度,一条为m,一条为n。这种方法的时间复杂度为O(m*n)
。方法二:
借助栈的后进先出特点。
两条单链表相交会有什么特点?它们相交后最后一个结点一定是同一个结点,可能是Y
或者>
,但是绝对不可能是X
。既然是这样,我们能不能考虑从链表的最后,向前开始遍历呢?如果最后两条链表的最后一个结点相同,则继续向前找有没有相同的结点,如果没有,则这个结点就是第一个公共结点,如果有,则继续向前找。
对于单链表,我们是没有办法从前向后遍历的,所以只能借助于栈,遍历两条链表,将他们分别压入一个栈,我们只要从栈顶开始比较即可
。假设两条链表的长度,一条为m,一条为n。这种方法的时间复杂度为O(m+n)
,空间复杂度也是O(m+n)
,所以这是一种用空间换取时间
的方法。方法三:
快慢指针的思想。
我们可以先求出两个链表的长度差,然后让长的那条链表先走长度差步,然后两条链表一起走,他们一定会在第一个公共结点处相遇。这种方法的时间复杂度为O(n+m)
,但是空间复杂度却为O(1)
。
由于前两种办法的时间复杂度或空间复杂度较高,面试官一般不会喜欢,所以这里只实现第三种方法:快慢指针的思想
代码实现:
//求两条链表的第一个公共结点
Node* GetMeetNode(pLinkList plist1, pLinkList plist2)
{
int len1 = 0;
int len2 = 0;
int gap = 0;
Node* cur1 = plist1;
Node* cur2 = plist2;
//求链表1长度
while (cur1)
{
len1++;
cur1 = cur1->next;
}
//求链表2长度
while (cur2)
{
len2++;
cur2 = cur2->next;
}
//求差值
gap = abs(len1 - len2);
cur1 = plist1;//长
cur2 = plist2;//短
if (len1 < len2)
{
cur1 = plist2;
cur2 = plist1;
}
//较长链表先走gap步
while (gap--)
{
cur1 = cur1->next;
}
//两个指针一起走一起走
while (cur1!=cur2)
{
cur1 = cur1->next;
cur2 = cur2->next;
}
return cur1;
}