剑指offer-37.两个链表的第一个公共结点

https://www.nowcoder.com/practice/6ab1d9a29e88450685099d45c9e31e46?tpId=13&tqId=11189&tPage=2&rp=1&ru=%2Fta%2Fcoding-interviews&qru=%2Fta%2Fcoding-interviews%2Fquestion-ranking

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

题解:
暴力,遍历一个链表,每遍历一个结点,在第二个链表上顺序遍历每个结点找到和第一个链表相同的结点。时间复杂度为 O(mn).

由于是有公共结点,而单向链表只有一个next指针指向下一个结点, 所以从第一个公共结点开始他们的后面的结点都是重合的,不可能再分叉。如下图所示。
这里写图片描述

思路一:
从头向前比较,最后一个相同的结点就是所求。但是单链表只能从头向后遍历,所以可以利用两个桟。先分别压桟,然后依次出栈,知道找到最后一个相同的结点。时间复杂度为O(m+n). 空间换时间。

思路二:
从头向后比较,先计算两个链表的长度差,然后让较长的链表先走长度差步,然后两个链表再一起后移,直到遇到相同的结点。时间复杂度为O(m+n)同时不需要辅助桟。

/*
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/
public class Solution {
    public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
        if (pHead1 == null || pHead2 == null) {
            return null;
        }
        int p1Length = getListLength(pHead1);
        int p2Length = getListLength(pHead2);
        ListNode pListHeadLong = pHead1;
        ListNode pListHeadShort = pHead2;
        if (p1Length < p2Length) {
            pListHeadLong = pHead2;
            pListHeadShort = pHead1;
        }
        // 现在长链表上走几步,再同时在两个链表上遍历
        for (int i = 0; i < Math.abs(p1Length - p2Length); i++) {
            pListHeadLong = pListHeadLong.next;
        }
        while (pListHeadLong != null && pListHeadShort != null && pListHeadLong != pListHeadShort) {
            pListHeadLong = pListHeadLong.next;
            pListHeadShort=pListHeadShort.next;
        }
        return pListHeadLong;
    }

    private int getListLength(ListNode pHead1) {
        int length = 1;
        while (pHead1.next != null) {
            length++;
            pHead1 = pHead1.next;
        }
        return length;
    }
}

猜你喜欢

转载自blog.csdn.net/zxm1306192988/article/details/81216869