algorithm-base/animation-simulation/链表篇/剑指Offer52两个链表的第一个公共节点.md
2021-07-13 13:43:15 +08:00

7.5 KiB
Raw Blame History

如果阅读时,发现错误,或者动画不可以显示的问题可以添加我微信好友 tan45du_one ,备注 github + 题目 + 问题 向我反馈

感谢支持,该仓库会一直维护,希望对各位有一丢丢帮助。

另外希望手机阅读的同学可以来我的 公众号:袁厨的算法小屋 两个平台同步,想要和题友一起刷题,互相监督的同学,可以在我的小屋点击刷题小队进入。

剑指 Offer 52. 两个链表的第一个公共节点 & 160. 相交链表

前言

今天给大家带来一个不是那么难的题目这个题目的解答方法很多只要能AC的就是好方法虽然题目不是特别难但是也是剑指offer上的经典题目所以大家要记得打卡呀。

然后今天我们的链表板块就算结束啦。周末的时候我会对链表的题目做一个总结,俗话说温故而知新嘛。好啦废话不多说,我们一起来看一下今天的题目吧!

题目描述:

输入两个链表,找出它们的第一个公共节点。如下图,返回黄色结点即可。

image-20201029215837844

题目表达是不是也很简单这个题目我的方法一共有两个一种就是用HashSet进行存储一种就是利用双指针大家有更好的可以在下面讨论呀。

HashSet

这个方法是比较简单的主要思路就是先遍历一个链表将链表的所有值都存到Hashset中然后再遍历另一个链表如果发现某个结点在Hashset中已经存在那我们直接返回该节点即可代码也很简单。

题目代码

Java Code:

public class Solution {
    public ListNode getIntersectionNode (ListNode headA, ListNode headB) {
        ListNode tempa = headA;
        ListNode tempb = headB;
        //定义Hashset
        HashSet<ListNode> arr = new HashSet<ListNode>();
        //遍历链表A将所有值都存到arr中
        while (tempa != null) {
            arr.add(tempa);
            tempa = tempa.next;
        }
        //遍历列表B如果发现某个结点已在arr中则直接返回该节点
        while (tempb != null) {
            if (arr.contains(tempb)) {
                return tempb;
            }
            tempb = tempb.next;
        }
        //若上方没有返回此刻tempb为null
        return tempb;
        
    }
}

C++ Code:

class Solution {
public:
    ListNode * getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode * tempa = headA;
        ListNode * tempb = headB;
        //定义Hashset
        set <ListNode *> arr;
        //遍历链表A将所有值都存到arr中
        while (tempa != nullptr) {
            arr.insert(tempa);
            tempa = tempa->next;
        }
        //遍历列表B如果发现某个结点已在arr中则直接返回该节点
        while (tempb != nullptr) {
            if (arr.find(tempb) != arr.end()) {
                return tempb;
            }
            tempb = tempb->next;
        }
        //若上方没有返回此刻tempb为null
        return tempb;
    }
};

JS Code:

var getIntersectionNode = function(headA, headB) {
    let tempa = headA;
    let tempb = headB;
    //定义Hashset
    let arr = new Set();
    //遍历链表A将所有值都存到arr中
    while (tempa) {
        arr.add(tempa);
        tempa = tempa.next;
    }
    //遍历列表B如果发现某个结点已在arr中则直接返回该节点
    while (tempb) {
        if (arr.has(tempb)) {
            return tempb;
        }
        tempb = tempb.next;
    }
    //若上方没有返回此刻tempb为null
    return tempb;
};

Python Code:

class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        tempa = headA
        tempb = headB
        # 定义Hashset
        arr = set()
        # 遍历链表A将所有值都存到arr中
        while tempa is not None:
            arr.add(tempa)
            tempa = tempa.next
        # 遍历列表B如果发现某个结点已在arr中则直接返回该节点
        while tempb is not None:
            if tempb in arr:
                return tempb
            tempb = tempb.next
        # 若上方没有返回此刻tempb为null
        return tempb

下面这个方法比较巧妙,不是特别容易想到,大家可以自己实现一下,这个方法也是利用我们的双指针思想。

下面我们直接看动图吧,特别直观,一下就可以搞懂。

第一次相交的点

是不是一下就懂了呀,我们利用双指针,当某一指针遍历完链表之后,然后掉头去另一个链表的头部,继续遍历。因为速度相同所以他们第二次遍历的时候肯定会相遇,是不是很浪漫啊!

题目代码

Java Code:

public class Solution {
    public ListNode getIntersectionNode (ListNode headA, ListNode headB) {
        //定义两个节点
        ListNode tempa = headA;
        ListNode tempb = headB;
        //循环
        while (tempa != tempb) {
          //如果不为空就指针下移,为空就跳到另一链表的头部
           tempa = tempa != null ? tempa.next: headB;
           tempb = tempb != null ? tempb.next: headA;
        }
        return tempa;//返回tempb也行
    }
}

C++ Code:

class Solution {
public:
    ListNode * getIntersectionNode(ListNode *headA, ListNode *headB) {
        //定义两个节点
        ListNode * tempa = headA;
        ListNode * tempb = headB;
        //循环
        while (tempa != tempb) {
           //如果不为空就指针下移,为空就跳到另一链表的头部
           tempa = tempa != nullptr ? tempa->next: headB;
           tempb = tempb != nullptr ? tempb->next: headA;
        }
        return tempa;//返回tempb也行
    }
};

JS Code:

var getIntersectionNode = function(headA, headB) {
    //定义两个节点
    let tempa = headA;
    let tempb = headB;
    //循环
    while (tempa != tempb) {
        //如果不为空就指针下移,为空就跳到另一链表的头部
        tempa = tempa != null ? tempa.next: headB;
        tempb = tempb != null ? tempb.next: headA;
    }
    return tempa;//返回tempb也行
};

Python Code:

class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        # 定义两个节点
        tempa = headA
        tempb = headB
        # 循环
        while tempa is not tempb:
            # 如果不为空就指针下移,为空就跳到另一链表的头部
            tempa = tempa.next if tempa is not None else headB
            tempb = tempb.next if tempb is not None else headA
        return tempa  # 返回tempb也行

好啦,链表的题目就结束啦,希望大家能有所收获,下周就要更新新的题型啦,继续坚持,肯定会有收获的。