前言:
我这脑子。唉,以前做过这道题的,还是想了好久。。。。。
题目描述
输入两个链表,找出它们的第一个公共结点。(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的)
解题思路
这道题刚开始一看,我们就可以想到暴力解法。我们先取出一个链表的结点,然后再另一个另一个链表进行遍历。这样循环求解。这样方法是不好的,时间复杂度达到了O(m*n)。所以不建议使用这种方法。
之后,我在好好理解一下这个题意。这是一个单链表,也就是只有一个指针指向下一结点。所以一旦链表有相同的结点,那么就说明这两个链表构成Y型结构的链表。所以这两个链表公共点之后的所有结点都是相同,所以我们可以从后向前遍历,直到找到不同结点的前一个结点,则就是公共结点。这里就需要用到两个辅助栈来实现。这里只提供方法没有具体实现。本例提供代码是方法三。
方法三就是我们可以先遍历一遍两个链表,然后算出两个链表的长度,然后计算出长度差,让长链表先走差值,这样这两个链表的就处于一个位置了,这样这开始遍历比较。这个实现也比较简单。这里有一个比较简单的代码实现。
创建两个指针p1和p2,分别指向两个链表的头结点,然后依次往后遍历。如果某个指针到达末尾,则将该指针指向另一个链表的头结点;如果两个指针所指的节点相同,则循环结束,返回当前指针指向的节点。比如两个链表分别为:1->3->4->5->6和2->7->8->9->5->6。短链表的指针p1会先到达尾部,然后重新指向长链表头部,当长链表的指针p2到达尾部时,重新指向短链表头部,此时p1在长链表中已经多走了k步(k为两个链表的长度差值),p1和p2位于同一起跑线,往后遍历找到相同节点即可。其实该方法主要就是用链表循环的方式替代了长链表指针先走k步这一步骤。
代码样例
package com.asong.leetcode.FindFirstCommonNode;
/**
* 两个链表的第一个公共结点
* 输入两个链表,找出它们的第一个公共结点。(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的)
*/
public class Solution {
public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
if(pHead1==null||pHead2==null)
{
return null;
}
ListNode p1 = pHead1;
ListNode p2 = pHead2;
while(p1!=p2)
{
p1 = p1.next;
p2 = p2.next;
if(p1!=p2)
{
if(p1==null) p1 = pHead1;
if(p2==null) p2 = pHead2;
}
}
return p1;
}
}