剑指offer:两个链表的第一个公共节点

题目描述

输入两个链表,找出它们的第一个公共结点。

思路1:暴力破解法,时间复杂度o(mn)

首先想到的就是暴力破解了,遍历第一个链表的每个节点,每遍历一个节点,都遍历第二个链表,将其与第二个链表中的每个节点作比较,如果相等,则返回该节点,否则,继续遍历。如果两个链表都遍历结束后都没有找到公共节点,则返回null。

剑指offer:两个链表的第一个公共节点_第1张图片

 

思路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;
    }
}

剑指offer:两个链表的第一个公共节点_第2张图片

     剑指offer:两个链表的第一个公共节点_第3张图片

 

不知道为什么,我提交到牛客的代码,暴力破解法竟然用时更短,空间也不大,疑惑!!!

思路三:借助Hashset,时间复杂度也是o(m+n),但是开辟了额外空间

 

剑指offer:两个链表的第一个公共节点_第4张图片

 

参考博客:

https://blog.csdn.net/weixin_40853073/article/details/81706773

你可能感兴趣的:(剑指offer)