题目描述
输入两个链表,找出它们的第一个公共结点。
思路1:暴力破解法,时间复杂度o(mn)
首先想到的就是暴力破解了,遍历第一个链表的每个节点,每遍历一个节点,都遍历第二个链表,将其与第二个链表中的每个节点作比较,如果相等,则返回该节点,否则,继续遍历。如果两个链表都遍历结束后都没有找到公共节点,则返回null。
思路2:求差法,时间复杂度o(m+n)
有公共结点的两个链表的特点,两个链表有公共结点,则这个链表从该结点开始,next指针都指向同一个结点,(我的理解,公共结点处,它们val值和next都是相等的)。因为链表是单向节点,所以从公共结点之后的结点肯定都是相同的。形如:
如果两个链表有公共结点,则从公共结点开始的后半截都是相同的。如果可以从链表尾部向前遍历,则最后一个相同的节点就是我们要找的结点。但是单向链表,只有一个指向后面的指针,没有向前的指针,因此不能采用这个方法。
由上图可以看出,可以让较长的链表先走半截,知道两个链表相同后,再开始遍历。
实现:
public class Solution {
public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
if(pHead1==null||pHead2==null) return null;
int len1=getLen(pHead1);
int len2=getLen(pHead2);
ListNode p1=pHead1;
ListNode p2=pHead2;
if(len1>len2){
int diff=len1-len2;
while(diff!=0){
p1=p1.next;
diff--;
}
}else{
int diff=len2-len1;
while(diff!=0){
p2=p2.next;
diff--;
}
}
while(p1!=null){
if(p1.val==p2.val){
return p1;
}
p1=p1.next;
p2=p2.next;
}
return null;
}
private int getLen(ListNode pHead){
int len=0;
while(pHead!=null){
len++;
pHead=pHead.next;
}
return len;
}
}
不知道为什么,我提交到牛客的代码,暴力破解法竟然用时更短,空间也不大,疑惑!!!
思路三:借助Hashset,时间复杂度也是o(m+n),但是开辟了额外空间
参考博客:
https://blog.csdn.net/weixin_40853073/article/details/81706773