leetcode160:相交链表

题目:

给你两个单链表的头节点 headAheadB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null

图示两个链表在节点 c1 开始相交**:**

题目数据 保证 整个链式结构中不存在环。

注意 ,函数返回结果后,链表必须 保持其原始结构

思路:

简单来说,就是求两个链表交点节点的指针

要注意:不是数值相等,而是指针相等

代码实现:

方法一:长度差

①先分别计算两个链表的长度,将curA指向长的链表,curB指向短的链表

②再将两个链表长度相减,得到差值

③让curA先走差值大小的长度,再同时移动两个指针

④最后返回相交的节点

cpp 复制代码
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode* curA = headA;
        ListNode* curB = headB;
        int lenA = 0, lenB = 0;
        while (curA != NULL) { // 求链表A的长度
            lenA++;
            curA = curA->next;
        }
        while (curB != NULL) { // 求链表B的长度
            lenB++;
            curB = curB->next;
        }
        curA = headA;
        curB = headB;
        // 让curA为最长链表的头,lenA为其长度
        if (lenB > lenA) {
            swap (lenA, lenB);
            swap (curA, curB);
        }
        // 求长度差
        int gap = lenA - lenB;
        // 让curA和curB在同一起点上(末尾位置对齐)
        while (gap--) {
            curA = curA->next;
        }
        // 遍历curA 和 curB,遇到相同则直接返回
        while (curA != NULL) {
            if (curA == curB) {
                return curA;
            }
            curA = curA->next;
            curB = curB->next;
        }
        return NULL;
    }
};

但是这种方法要遍历链表两次,一次得到长度,一次寻找节点,我们可以使用哈希表来存储遍历过的节点,如果当前节点已经在哈希表中存在,就直接返回

方法2:哈希表

①先遍历一遍其中一个链表,将里面的节点存入哈希表中

②再遍历另一个链表,判断链表中的节点是否存在哈希表中

③如果存在就说明相交,全部遍历完还没找到相交节点说明不相交

cpp 复制代码
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        if (!headA || !headB) return nullptr;        
        unordered_set<ListNode*> visited;
        ListNode* curr = headA;
        // 第一遍遍历链表A,将所有节点加入哈希表
        while (curr) {
            visited.insert(curr);
            curr = curr->next;
        }
        // 第二遍遍历链表B,检查节点是否已在哈希表中
        curr = headB;
        while (curr) {
            if (visited.find(curr) != visited.end()) {
                return curr;  // 找到第一个公共节点
            }
            curr = curr->next;
        }        
        return nullptr;  // 没有交点
    }
};

哈希表的方法比较清晰简单,但是需要使用到额外的空间,可以使用双指针的方式,避免额外空间的使用

方法3.双指针

①将两个指针分别指向两个链表的头节点

②当两个指针不相同时,分别移动两个指针

③当其中一个指针指向当前链表结尾时,将其移动到另一个链表的头节点,继续遍历

④若相交,两个指针一定会在相交节点相遇,若不相交,两个指针一定会同时指向最后的NULL节点

cpp 复制代码
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        if(headA==nullptr||headB==nullptr)return nullptr;
        ListNode* h1 = headA;
        ListNode* h2 = headB;
        while(h1!=h2){
            //如果遍历完当前链表,就将其移动到另一个链表的头节点
            if(h1==nullptr){
                h1 = headB;
            }else{
                h1 = h1->next;
            }
            if(h2==nullptr){
                h2 = headA;
            }else{
                h2=h2->next;
            }
        }
        return h1;
    }
};

双指针的方法没有使用到额外的空间,并且时间复杂度是O(n+m),属于是较优的解法了

这题我们从最开始的两次遍历,到使用额外空间的一次遍历,再到不使用额外空间的一次遍历,多次优化代码,说明一道题不只有一种解法,可以进行不断的优化,找到最优解

相关推荐
XX風13 分钟前
8.1 PFH&&FPFH
图像处理·算法
NEXT0626 分钟前
前端算法:从 O(n²) 到 O(n),列表转树的极致优化
前端·数据结构·算法
代码游侠1 小时前
学习笔记——设备树基础
linux·运维·开发语言·单片机·算法
想进个大厂1 小时前
代码随想录day37动态规划part05
算法
sali-tec1 小时前
C# 基于OpenCv的视觉工作流-章22-Harris角点
图像处理·人工智能·opencv·算法·计算机视觉
子春一1 小时前
Flutter for OpenHarmony:构建一个 Flutter 四色猜谜游戏,深入解析密码逻辑、反馈算法与经典益智游戏重构
算法·flutter·游戏
人道领域2 小时前
AI抢人大战:谁在收割你的红包
大数据·人工智能·算法
TracyCoder1232 小时前
LeetCode Hot100(34/100)——98. 验证二叉搜索树
算法·leetcode
A尘埃2 小时前
电信运营商用户分群与精准运营(K-Means聚类)
算法·kmeans·聚类
power 雀儿3 小时前
掩码(Mask)机制 结合 多头自注意力函数
算法