两个链表的第一个公共节点

题目描述

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

解法一:

借助辅助空间,可以记录下链表一中的所有节点,再遍历链表二,每遍历到一个节点都判断该节点是否在链表一中存在,第一个存在的节点便是要求节点。

这种解法在链表较短时可以接受,但是数据量增加后产生的空间代价便让人无法接受。

public class Solution {
    public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
        Set set = new HashSet();
        while(pHead1 != null) {
            set.add(pHead1);
            pHead1 = pHead1.next;
        }
        while(pHead2 != null) {
            if(set.contains(pHead2)) {
                return pHead2;
            }
            pHead2 = pHead2.next;
        }
        return null;
    }
}
解法二:

思想与链表中倒数第K个节点这道题目有点像。先遍历一边链表一,记录下长度m,再遍历链表二,记录下长度n。假设m> n。

若链表一和二有公共节点,则从第一个公共节点开始到末点均为公共点。那么让链表一从第(m-n+1)个点,链表二从第一个点开始同时跑,二者相遇的点便是公共点。即使链表一和链表二没有公共点,那么二者最终相遇于两个null节点,返回null。

public class Solution {
    public static ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
        int m = 0, n = 0;
        ListNode p1 = pHead1, p2 = pHead2;
        while(p1 != null) {
            m++;
            p1 = p1.next;
        }
        while(p2 != null) {
            n++;
            p2 = p2.next;
        }
        for(int i = 0; i < m - n; i++) {
            if(m > n)
                pHead1 = pHead1.next;
            else
                pHead2 = pHead2.next;
            }
        while(pHead1 != pHead2) {
            pHead1 = pHead1.next;
            pHead2 = pHead2.next;
        }
        return pHead1;
    }
}
解法三:

这种方法思路与方法二很像,但是更巧妙。假设链表一长度为m,链表二长度为n,这两个链表有公共点,公共长度为k。
设指针p1指向链表一的头,p2指向链表2的头。
p1遍历完链表一后跳转指向链表二的头,再对链表二进行遍历直到末尾。
p2遍历完链表二后跳转指向链表一的头,再对链表一进行遍历直到末尾。
则,p1走过的路程为m+n-k,p2走过的路程为m+n-k,二者相同。
现在我们让p1和p2同时出发,每次同时指向下一个节点。则二者肯定同时遍历完链表一和链表二,相遇于null。

我们通过图片来演示过程:

上边为链表一,下边为链表二,白色箭头为p1,黑色箭头为p2

(1)p1与p2均指向各自的链表头

[图片上传中...(image-3a3fa-1561189902540-4)]

(2)p1与p2同时移动

image

(3)p2移动到末尾后跳转到链表一的头,p1和p2依旧同时移动

image

(4)当p1也移动到末尾并跳转到链表二的头部时,此时p1与p2并列前行。因为二者要经过的总距离均为m+n-k,必定同时到达终点,##定是并列前行。

image

(5)p1与p2第一次相遇的点便为公共点。若无公共点,则相遇于两个null节点。

image

你可能感兴趣的:(两个链表的第一个公共节点)