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

一、需求

  • 输入两个链表,找出它们的第一个公共节点。
  • 如下面的两个链表

       

  • 在节点 c1 开始相交。

二、双指针(暴力)

2.1  思路分析

  1. 采用双重循环,使用两个指针p、q分别指向链表A和链表B,外循环遍历链表A,内循环遍历链表B,每次判断当前链表A的节点是否就是当前链表B的节点,如果是就返回该节点,否则就一直遍历,直到链表A遍历结束;
  2. 如果不存在公共结点,则返回null;
  3. 因为本题要求时间复杂度限制在O(1),故该方法在运行时会出现超时;

2.2  代码实现

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode p = headA;
        while(p != null) {
            ListNode q = headB;
            while(q != null) {
                if(p == q) return p;
                q = q.next;
            }
            p = p.next;
        }
        return null;
    }
}

2.3  复杂度分析

  • 时间复杂度为O(n^2),因为采用了双重循环,计算次数为n^2;
  • 空间复杂度为O(1),变量p,q占用常数大小的额外空间;

三、双指针法(优化)

3.1  思路分析

  1. 假设链表A、B存在公共节点,链表A头节点距离公共节点为L1步,即[A头节点,公共节点),链表B头节点距离公共节点为L2步,即[B头节点,公共节点),两个链表的公共部分长度为C;
  2. 那么根据L1+C+L2 = L2+C+L1的原理,设指针p,q指向链表A,B,p,q同时移动,当p走过L1+C+L2后,q走过L2+C+L1后,它们会在公共结点相遇;

3.2  代码实现

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode p = headA;
        ListNode q = headB;
        while(p != q) {
            //这里让双指针同时移动,避免了循环
            p = p != null ? p.next : headB;
            q = q != null ? q.next : headA;
        }
        return p;
    }
}

3.3  复杂度分析

  • 时间复杂度为O(n);
  • 空间复杂度为O(1);

四、学习地址

作者:腐烂的橘子

链接:https://leetcode-cn.com/problems/liang-ge-lian-biao-de-di-yi-ge-gong-gong-jie-dian-lcof/solution/shuang-zhi-zhen-fa-lang-man-xiang-yu-by-ml-zimingm/

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页