【LeetCode_160】相交链表

刷爆LeetCode系列

LeetCode第160题:

github地址

有梦想的电信狗

前言

本文用C++实现LeetCode第160题


题目描述

题目链接https://leetcode.cn/problems/intersection-of-two-linked-lists/description/



题目与思路分析

目标分析

  1. 给定两个单链表的头节点 headAheadB ,找出并返回两个单链表相交的起始节点

  2. 如果两个链表不存在相交节点,返回 nullptr

  3. 提高要求 :时间复杂度为O(m + n),空间复杂度为O(1),其中mn分别为两个链表的长度

思路一:暴力解法

思路 :两层循环:遍历链表A和链表B,将链表A中的每个结点的地址都和链表B中的每个结点的地址进行比较,如果地址相等,则相交。

操作

  • ListNode* curNode1 = headA, *curNode2 = headBcurNode1curNode2分别用于迭代遍历两个链表

  • 链表A中的每个节点 需要和链表B中的每个结点进行比较

    cpp 复制代码
      while(curNode1){
          while(curNode2){
              if(curNode1 == curNode2)
                  return curNode1;
              else
                  curNode2 = curNode2->next;
          }
          curNode1 = curNode1->next;
          curNode2 = headB;
      }
    • curNode1 == curNode2时:代表是相交的结点,返回当前结点即可

    • else:内层循环中,curNode2移向下一个节点

  • 内层循环结束一轮后

    • 链表A的curNode1向后移动:curNode1 = curNode1->next
    • 链表B的迭代结点回到链表B的头结点,准备进行下一轮遍历:curNode2 = headB;
  • 循环内没有return时,代表没有相交。循环结束后return nullptr;

  • 时间复杂度O(n^2),空间复杂度O(1)

思路二:快慢指针

思路快慢指针解法

  1. 先分别求两个链表的长度
  2. 长的链表的curNode指针先向后移动两个链表长度的差距步
  3. 两个迭代指针再同时移动,第一个地址相同的结点就是交点

操作

  • ListNode* curNode1 = headA, *curNode2 = headBcurNode1curNode2分别用于迭代遍历两个链表

  • 求链表长度的子函数

    cpp 复制代码
      private:
          size_t getLength(ListNode* list){
              ListNode* curNode = list;
              size_t length = 0;
              while(curNode){
                  ++length;
                  curNode = curNode->next;
              }
              return length;
          }
  • 分别求两个链表的长度

    • size_t lengthA = getLength(headA)size_t lengthB = getLength(headB);
  • 比较两个链表的长度 ,长的链表的curNode指针先移动差距步

  • 再让两个curNode指针同时移动,第一个相同的地址就是交点

  • 时间复杂度O(m + n),空间复杂度O(1)

代码实现

思路一:暴力解法

  • 暴力解法 :时间复杂度O(n^2),空间复杂度O(1)
cpp 复制代码
// 暴力解法 O(n^2)
class Solution {
public:
    ListNode* getIntersectionNode(ListNode* headA, ListNode* headB) {
        ListNode* curNode1 = headA, *curNode2 = headB;
        while(curNode1){
            while(curNode2){
                if(curNode1 == curNode2)
                    return curNode1;
                else
                    curNode2 = curNode2->next;
            }
            curNode1 = curNode1->next;
            curNode2 = headB;
        }
        return nullptr;
    }
};

思路二:快慢指针

  • 快慢指针解法 :时间复杂度O(m + n),空间复杂度O(1),其中mn分别为两个链表的长度
cpp 复制代码
// 时间复杂度为O(m + n)的解法
class Solution {
public:
    ListNode* getIntersectionNode(ListNode* headA, ListNode* headB) {
        ListNode* curNode1 = headA, *curNode2 = headB;
        // 分别求两个链表的长度
        size_t lengthA = getLength(headA);
        size_t lengthB = getLength(headB);
        // 长的链表先走差距步
        if(lengthA > lengthB){
            size_t gap = lengthA - lengthB;
            while(gap--)
                curNode1 = curNode1->next;
        }
        else{
            size_t gap = lengthB - lengthA;
            while(gap--)
                curNode2 = curNode2->next;
        }
        // 两个链表再同时走,第一个相同的地址就是交点
        while(curNode1){
            if(curNode1 == curNode2)
                return curNode1;
            else{
                curNode1 = curNode1->next;
                curNode2 = curNode2->next;
            }
        }
        return nullptr;
    }
private:
    size_t getLength(ListNode* list){
        ListNode* curNode = list;
        size_t length = 0;
        while(curNode){
            ++length;
            curNode = curNode->next;
        }
        return length;
    }
};

算法代码优化

  • 思路二代码优化 :优化比较链表长度的逻辑,减少逻辑重复的代码
cpp 复制代码
// 优化找长链表的逻辑  时间复杂度为O(m + n)的解法
class Solution {
public:
    ListNode* getIntersectionNode(ListNode* headA, ListNode* headB) {
        ListNode* curNode1 = headA, *curNode2 = headB;
        // 分别求两个链表的长度
        size_t lengthA = getLength(headA);
        size_t lengthB = getLength(headB);
        // 长的链表先走差距步
        // 优化找长的链表的逻辑 ,假设A比B长,再加一个修正假设的逻辑
        ListNode* longList = headA, *shortList = headB;
        size_t gap = lengthA - lengthB;
        if(lengthA < lengthB){
            longList = headB;
            shortList = headA;
            gap = lengthB - lengthA;
        }
        // 长链表先走差距步
        while(gap--)
            longList = longList->next;
       
        // 两个链表再同时走,第一个相同的地址就是交点
        while(longList){
            if(longList == shortList)
                return longList;
            else{
                longList = longList->next;
                shortList = shortList->next;
            }
        }
        return nullptr;
    }
private:
    size_t getLength(ListNode* list){
        ListNode* curNode = list;
        size_t length = 0;
        while(curNode){
            ++length;
            curNode = curNode->next;
        }
        return length;
    }
};

以上就是本文的所有内容了,如果觉得文章对你有帮助,欢迎 点赞⭐收藏 支持!如有疑问或建议,请在评论区留言交流,我们一起进步

分享到此结束啦
一键三连,好运连连!

你的每一次互动,都是对作者最大的鼓励!


征程尚未结束,让我们在广阔的世界里继续前行! 🚀

相关推荐
秋邱1 分钟前
Java包装类:基本类型与包装类转换、自动装箱与拆箱原理
java·开发语言·python
海上彼尚2 分钟前
Go之路 - 8.go的接口
开发语言·golang·xcode
乐茵lin2 分钟前
golang context底层设计探究
开发语言·后端·golang·大学生·设计·context·底层源码
lkbhua莱克瓦244 分钟前
基础-约束
android·开发语言·数据库·笔记·sql·mysql·约束
拉拉拉拉拉拉拉马6 分钟前
感知机(Perceptron)算法详解
人工智能·python·深度学习·算法·机器学习
Alex Cafu7 分钟前
Linux网络编程2(HTTP 协议、IO 多路复用)
linux·c语言·网络·http
falldeep7 分钟前
LeetCode高频SQL50题总结
数据结构·数据库·sql·算法·leetcode·职场和发展
万邦科技Lafite7 分钟前
淘宝开放API获取订单信息教程(2025年最新版)
java·开发语言·数据库·人工智能·python·开放api·电商开放平台
CoderCodingNo7 分钟前
【GESP】C++五级真题(前缀和思想考点) luogu-P10719 [GESP202406 五级] 黑白格
开发语言·c++·算法
阿珊和她的猫7 分钟前
页面停留时长埋点实现技术详解
开发语言·前端·javascript·ecmascript