【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;
    }
};

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

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

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


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

相关推荐
稚南城才子,乌衣巷风流35 分钟前
ST 表(Sparse Table)算法详解:原理、实现与应用
算法
hold?fish:palm41 分钟前
9 找到字符串中所有字母异位词
c++·算法·leetcode
小大宇1 小时前
python flask框架 SSE流式返回、跨域、报错
开发语言·python·flask
Sw1zzle1 小时前
算法入门(六):贪心算法 - 基础入门(Leetcode 121/455/860/376/738)
算法·leetcode·贪心算法
青山木1 小时前
Hot 100 --- 岛屿数量
java·数据结构·算法·leetcode·深度优先·广度优先
柒星栈1 小时前
PHP 源码怎么加密防破解?三套方案实战指南
开发语言·php·android studio
不会就选b2 小时前
算法日常・每日刷题--<归并排序>1
数据结构·算法
勉灬之2 小时前
Next.js + Prisma 跨平台部署踩坑记
开发语言·javascript·ecmascript
危桥带雨2 小时前
排序算法(快排、归并、计数、基数排序)
数据结构·算法·排序算法