[链表]9.两个链表的第一个公共节点[华为,小红书]

题目:输入两个链表,找出它们的第一个公共结点。(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的)

解答:

方法一:双指针法

创建两个指针p1和p2,分别指向两个链表的头结点,然后依次往后遍历。如果某个指针到达末尾,则将该指针指向另一个链表的头结点;如果两个指针所指的节点相同,则循环结束,返回当前指针指向的节点。比如两个链表分别为:1->3->4->5->6和2->7->8->9->5->6。短链表的指针p1会先到达尾部,然后重新指向长链表头部,当长链表的指针p2到达尾部时,重新指向短链表头部,此时p1在长链表中已经多走了k步(k为两个链表的长度差值),p1和p2位于同一起跑线,往后遍历找到相同节点即可。其实该方法主要就是用链表循环的方式替代了长链表指针先走k步这一步骤。

/*
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;
        ListNode p1 = pHead1;
        ListNode p2 = pHead2;
        while(p1 != p2){
            p1 = p1.next;
            p2 = p2.next;
            if(p1 != p2){
                if(p1 == null) p1 = pHead2;
                if(p2 == null) p2 = pHead1;
            }
        }
        return p1;
    }
}

方法二:长链表先走,再同步遍历
两个链表比较长短,计算出两者的长度差x,比较长的链表先往前走x步,然后长短链表一起同步向前走,看遍历到的节点是否相同,如果相同就是第一个公共节点。

/*
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;
        if (pHead1 == pHead2) return pHead1;
        int len1 = getLength(pHead1);
        int len2 = getLength(pHead2);
        //让比较长的链表先走几步
        if (len1 > len2) {
            for (int i = 0; i < (len1 - len2); i++) {
                pHead1 = pHead1.next;
            }
        } else {
            for (int i = 0; i < (len2 - len1); i++) {
                pHead2 = pHead2.next;
            }
        }
        boolean flag = false;  //标志位,判断是否走到第一个公共节点
        ListNode result = null;
        while (!flag) {
            if (pHead1 == null || pHead2 == null) {
                return null;
            }
            if (pHead1.val == pHead2.val) {
                flag = true;
                result = pHead1;
            } else {
                pHead1 = pHead1.next;
                pHead2 = pHead2.next;
            }
        }
        return result;
    }

    /*求链表长度的方法,每次求链表长度,需要遍历一次单链表*/
    public static int getLength(ListNode pHead) {
        int len = 1;
        ListNode current = pHead;
        while (current.next != null) {
            len++;
            current = current.next;
        }
        return len;
    }
}

方法三:用hashMap数据结构
第一个while循环遍历第一个链表,将其所有节点放入hashmap中
第二个while遍历第二个链表,用containsKey判断这个节点值是否存在第一个链表中。
(这种思路基本上就是用空间换时间)


方法四:两个链表的公共节点一定在链表的尾部
若连个链表存在公共节点,则它们的尾部一定从第一个公共节点开始完全相同。

我们分析有公共结点的两个链表有哪些特点。从链表结点的定义可以看出,这两个链表是单链表。如果两个单向链表有公共的结点,那么这两个链表从某一结点开始,它们的next都指向同一个结点,但由于是单向链表的结点,之后他们所有结点都是重合的,不可能再出现分叉。所以两个有公共结点而部分重合的链表,拓扑形状开起来像一个Y,而不可能像X

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

    ListNode(int val) {
        this.val = val;
    }
}*/
public class Solution {
   public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
        ListNode l1 = pHead1, l2 = pHead2;
        while (l1 != l2) {
            l1 = (l1 == null) ? pHead2 : l1.next;
            l2 = (l2 == null) ? pHead1 : l2.next;
        }
        return l1;
    }
}


https://www.jianshu.com/p/8ab784edaba5

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值