两个链表的第一个公共节点 -剑指Offer第52题

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

如下面的两个链表:
在这里插入图片描述
注意:

  • 如果两个链表没有交点,返回 null.
  • 在返回结果后,两个链表仍须保持原有的结构。
  • 可假定整个链表结构中没有循环。
  • 程序尽量满足 O(n) 时间复杂度,且仅用 O(1) 内存。

解题思路:

可以先计算两个链表的长度,长度差为n,首先,比较长的链表header先往后移动n步,然后两个链表一起往后移动,如果一样,则为公共节点。

package com.alibaba.study.offer;

/**
 * @Auther: wjj
 * @Date: 2020/12/16 18:43
 * @Description:
 */
public class Offer52 {

    public static void main(String[] args) {
        ListNode node1 = new ListNode(4);
        ListNode node2 = new ListNode(1);
        ListNode node3 = new ListNode(8);
        ListNode node4 = new ListNode(4);
        ListNode node5 = new ListNode(5);

        ListNode node6 = new ListNode(5);
        ListNode node7 = new ListNode(0);

        ListNode headA = node1;
        node1.next = node2;
        node2.next = node3;
        node3.next = node4;
        node4.next = node5;

        node6.next = node7;
        node7.next = node2;
        ListNode headB = node6;

        ListNode intersectionNode = getIntersectionNode(headA, headB);
        System.out.printf("end...");
    }

    public static ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        int lenA = 0;
        int lenB = 0;
        ListNode tempA = headA;
        while (tempA != null){
            lenA++;
            tempA = tempA.next;
        }
        ListNode tempB = headB;
        while (tempB != null){
            lenB++;
            tempB = tempB.next;
        }
        int substract = 0;
        if(lenA > lenB){
            substract = lenA - lenB;
            while (substract > 0){
                headA = headA.next;
                substract--;
            }
        } else {
            substract = lenB - lenA;
            while (substract > 0){
                headB = headB.next;
                substract--;
            }
        }
        ListNode start = null;
        while (headA != null){
            if(headA.val == headB.val && start == null){
                start = headA;
            } else if(headA.val != headB.val){
                start = null;
            }
            headA = headA.next;
            headB = headB.next;
        }
        return start == null ? null : start.next;
    }
}

class ListNode {
    int val;
    ListNode next;
    ListNode(int x) {
        val = x;
        next = null;
    }
 }

解法二:

我们使用两个指针 node1,node2 分别指向两个链表 headA,headB 的头结点,然后同时分别逐结点遍历,当 node1 到达链表 headA 的末尾时,重新定位到链表 headB 的头结点;当 node2 到达链表 headB 的末尾时,重新定位到链表 headA 的头结点。
这样,当它们相遇时,所指向的结点就是第一个公共结点。

 public ListNode getIntersectionNode2(ListNode headA, ListNode headB) {
     ListNode a = headA;
     ListNode b = headB;
     while (headA != headB) {
         headA = headA != null ? headA.next : b;
         headB = headB != null ? headB.next : a;
     }
     return headA;
 }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值