【算法与数据结构】160、LeetCode相交链表

news2024/11/16 19:26:52

文章目录

  • 一、题目
  • 二、解法
  • 三、完整代码

所有的LeetCode题解索引,可以看这篇文章——【算法和数据结构】LeetCode题解。

一、题目

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

二、解法

  思路分析:这道题题目蛮长的。说的大概意思就是对比指针地址,只要相等了,那就是相交节点。如果设置两个指针挨个遍历两个链表,那么复杂度非常高, O ( m ∗ n ) O(m*n) O(mn)。那么如何达到进阶的要求呢?首先我们要注意到,从相交节点开始,往后的节点是相同的(节点的下一个节点有且仅有一个),此外,链表是有长有短的,意味着长链表第lenB-lenA个节点之前不会是相交节点,那我们就从第lenB-lenA个节点开始查。如图,我们将两个链表分开右对齐放置,依次对比curA curB的地址,直到找到相交节点。关键点在于右对齐放置以后从最后节点开始,往前的节点位置上都是一一对应的,充分利用相交节点往后的节点都是相同节点的特点。
在这里插入图片描述
  程序如下

class Solution {
public:
    ListNode* getIntersectionNode(ListNode* headA, ListNode* headB) {
        ListNode* curA = headA;
        ListNode* curB = headB;
        int lenA = 0;
        int lenB = 0;
        while (curA != NULL) {  // 链表A长度
            curA = curA->next;
            lenA++;
        }
        curA = headB;
        while (curB != NULL) {  // 链表B长度
            curB = curB->next;
            lenB++;
        }
        curA = headA;
        curB = headB;
        if (lenA < lenB) {      // 选出长链表A
            swap(lenA, lenB);
            swap(curA, curB);
        }
        int index = lenA - lenB;
        while (index--) {   // A B链表右对齐
            curA = curA->next;
        }
        while (curA != curB && curA != NULL) {  // 对比地址
            curA = curA->next;
            curB = curB->next;
        }
        return curA == NULL ? NULL : curA;
    }
};

复杂度分析:

  • 时间复杂度: O ( m + n ) O( m + n) O(m+n), 用来计算两个链表的长度。
  • 空间复杂度: O ( 1 ) O(1) O(1)

三、完整代码

  下面代码当中添加了测试主程序,难点在于相交节点的生成。这里我用【算法与数据结构】707、LeetCode设计链表的链表类,重载了addAtIndex将相交节点加进去。

# include <iostream>
using namespace std;

// 定义链表节点类结构体
struct ListNode {
    int val;
    ListNode* next;
    ListNode() : val(0), next(NULL) {};
    ListNode(int input_val) : val(input_val), next(NULL) {};
    ListNode(int input_val, ListNode* input_next) : val(input_val), next(input_next) {};
};

// 链表类
class MyLinkedList {
public:
    // 构造函数
    MyLinkedList() {
        _FakeNode = new ListNode(0, NULL);    // 虚假头结点
        _size = 0;
    }
    // 成员函数
    void addAtIndex(int index, int val);
    void addAtIndex(int index, ListNode* InterNode);
    void ChainGenerator(int arr[], int len);
    void LinkListPrint(string str);
    // 成员变量
    int _size;
    ListNode* _FakeNode;
};

// 在指定位置添加值
void MyLinkedList::addAtIndex(int index, int val) {
    if (index > _size) return;
    if (index < 0) index = 0;
    ListNode* cur = _FakeNode; // 虚结点 
    // 需要断开上一一个阶段的链接,从插入位置的上一个索引开始处理
    while (index--) {
        cur = cur->next;
    }
    ListNode* pNewNode = new ListNode(val, cur->next);
    cur->next = pNewNode;
    _size++;
}

// 重载addAtIndex函数
void MyLinkedList::addAtIndex(int index, ListNode * InterNode) {
    if (index > _size) return;
    if (index < 0) index = 0;
    ListNode* cur = _FakeNode; // 虚结点 
    // 需要断开上一一个阶段的链接,从插入位置的上一个索引开始处理
    while (index--) {
        cur = cur->next;
    }
    InterNode->next = cur->next;
    cur->next = InterNode;
    _size++;
}

void MyLinkedList::ChainGenerator(int arr[], int len) {
    if (_FakeNode->next != NULL) return;
    ListNode* head = new ListNode(arr[0], NULL);
    ListNode* p = head;
    for (int i = 1; i < len; i++) {
        ListNode* pNewNode = new ListNode(arr[i], NULL);
        p->next = pNewNode; // 上一个节点指向这个新建立的节点
        p = pNewNode; // p节点指向这个新的节点
    }
    _FakeNode->next = head;
    _size = len;
}

void MyLinkedList::LinkListPrint(string str) {
    cout << str << endl;
    ListNode* cur = _FakeNode;
    while (cur->next != NULL) {
        cout << cur->next->val << ' ' << cur->next << ' ';
        cur = cur->next;
    }
    cout << endl;
}

class Solution {
public:
    ListNode* getIntersectionNode(ListNode* headA, ListNode* headB) {
        ListNode* curA = headA;
        ListNode* curB = headB;
        int lenA = 0;
        int lenB = 0;
        while (curA != NULL) {  // 链表A长度
            curA = curA->next;
            lenA++;
        }
        curA = headB;
        while (curB != NULL) {  // 链表B长度
            curB = curB->next;
            lenB++;
        }
        curA = headA;
        curB = headB;
        if (lenA < lenB) {      // 选出长链表A
            swap(lenA, lenB);
            swap(curA, curB);
        }
        int index = lenA - lenB;
        while (index--) {   // A B链表右对齐
            curA = curA->next;
        }
        while (curA != curB && curA != NULL) {  // 对比地址
            curA = curA->next;
            curB = curB->next;
        }
        return curA == NULL ? NULL : curA;
    }
};

int main()
{
    int arrA[] = { 4, 1, 4, 5 };
	int lenA = sizeof(arrA) / sizeof(int);
    int arrB[] = { 5, 6, 1, 4, 5 };
	int lenB = sizeof(arrB) / sizeof(int);
    int val = 2;
    ListNode* Node = new ListNode(2, NULL);
    MyLinkedList m1;
    MyLinkedList m2;
    m1.ChainGenerator(arrA, lenA);
    m2.ChainGenerator(arrB, lenB);
    m1.addAtIndex(3, Node);
    m2.addAtIndex(1, Node);
    m1.LinkListPrint("链表A:");
    m2.LinkListPrint("链表B:");
    Solution s1;
	ListNode* InterNode = s1.getIntersectionNode(m1._FakeNode->next, m2._FakeNode->next);
    if (InterNode != NULL) {
        cout << "相交节点的值:" << endl;
        cout << InterNode->val << endl;
    }
	system("pause");
	return 0;
}

end

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/637190.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

华为OD机试之执行时长(Java源码)

执行时长 题目描述 为了充分发挥GPU算力&#xff0c;需要尽可能多的将任务交给GPU执行&#xff0c;现在有一个任务数组&#xff0c;数组元素表示在这1秒内新增的任务个数且每秒都有新增任务。 假设GPU最多一次执行n个任务&#xff0c;一次执行耗时1秒&#xff0c;在保证GPU不空…

论文解读 | 机器人路径跟踪的受控纯追踪法

原创 | 文 BFT机器人 01 摘要 这篇文章是关于机器人路径跟踪的受控纯追踪算法的研究。文章介绍了传统的纯追踪算法以及相关变体&#xff0c;并提出了受控纯追踪算法作为本文的主要贡献。该算法旨在适应实际环境中的服务和工业移动机器人&#xff0c;提供方法来调整机器人的平移…

关于spring boot报javax/servlet/MultipartConfigElement错误以及的问题

springboot在启动时报java.lang.NoClassDefFoundError: javax/servlet/MultipartConfigElement 解决方法&#xff1a;将pom.xml文件中的provided删掉

盛元广通生物化学重点实验室化学品信息化安全管理系统

生物化学重点实验室是国家基础研究和高技术研究的重要基地&#xff0c;是培养和造就高层次创新型人才的重要基地。为保障实验室化学品安全使用&#xff0c;实验人员可通过现场或移动端管理系统实现化学品安全使用与存储。盛元广通生物化学重点实验室化学品信息化安全管理系统具…

方波信号拆分及合成

1. 前言 数字处理器产生的都是方波信号&#xff0c; 做EMC会有各种高频率的辐射超标。比如下图为EMC测试辐射图&#xff0c;其中480MHz左右频率超标&#xff0c;那么就需要分析这个频率是谁产生的&#xff0c;但是整个系统都没有谁使用了这么高的频率信号。但是一般根据经验都知…

mysql-explain-其他

eq_ref 主键和唯一索引的所有部分被连接使用&#xff0c;最多只会返回一条符合条件的记录【主键关联查询】 ref: 根节点二分查找 没有使用唯一索引&#xff0c;而是走了普通索引【二级索引】或者唯一索引的部分前缀&#xff0c;有可能查出多个符合条件的行。 range 范围扫…

全网最全的Python教程(非常详细),从零基础入门到上岗!

Python的火&#xff0c;有目共睹。Python陆续登上了IEEE、PYPL排行榜单之首&#xff0c;对于Python的崛起TIOBE排行榜也给予了回应&#xff1a;由于全球流行度在过去一年中涨幅最高&#xff01; 同时人工智能的兴起&#xff0c;也给了Python无限可能&#xff0c;让Python越来越…

Systick实现中断-GD32

定时器中断-GD32 include "gd32f10x.h" #include "systick.h" #include "LED.h"volatile static uint32_t delay_reload; volatile static uint32_t delay_value;/*!\brief configure systick\param[in] none\param[out] none\retval …

asp.net试卷自动生成系统VS开发sqlserver数据库web结构c#编程Microsoft Visual Studio

一、源码特点 asp.net试卷自动生成系统 是一套完善的web设计管理系统&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为vs2010&#xff0c;数据库为sqlserver2008&#xff0c;使用c#语言开发 asp.net试卷自动生成系统VS开发sq…

Java 泛型:概念、语法和应用

文章目录 一、什么是 Java 泛型&#xff1f;二、为什么要使用泛型三、Java 泛型的语法四、Java 泛型的应用五、Java 泛型的示例六、总结 随着 Java 编程语言的不断发展和更新&#xff0c;Java 1.5 版本引入了一项全新的特性——Java 泛型&#xff08;Java Generic&#xff09;&…

Classic AUTOSAR专题 | I/O模块简介

书接上回&#xff0c;上期专题内容中小怿介绍了Classic AUTOSAR之存储模块&#xff0c;相信大家对存储以及NvM已经有了初步的认识了解。接下来我们将继续介绍Classic AUTOSAR专题之I/O模块&#xff0c;同时感兴趣的小伙伴还请持续关注后续内容~ 01 AUTOSAR I/O功能概述 I/O(Inp…

2023年6月DAMA-CDGA/CDGP数据治理工程师认证这里报名

DAMA认证为数据管理专业人士提供职业目标晋升规划&#xff0c;彰显了职业发展里程碑及发展阶梯定义&#xff0c;帮助数据管理从业人士获得企业数字化转型战略下的必备职业能力&#xff0c;促进开展工作实践应用及实际问题解决&#xff0c;形成企业所需的新数字经济下的核心职业…

深度学习应用篇-自然语言处理-命名实体识别[9]:BiLSTM+CRF实现命名实体识别、实体、关系、属性抽取实战项目合集(含智能标注)【下篇】

【深度学习入门到进阶】必看系列&#xff0c;含激活函数、优化策略、损失函数、模型调优、归一化算法、卷积模型、序列模型、预训练模型、对抗神经网络等 专栏详细介绍&#xff1a;【深度学习入门到进阶】必看系列&#xff0c;含激活函数、优化策略、损失函数、模型调优、归一化…

ZYNQ 7020 开发板开机检测

拿到开发板后检测开发板能否正常工作。 检测需要的工具&#xff1a;电脑、显示器(有HDMI接口)、HDMI线、鼠标、键盘、网线、USB转串口驱动软件。 在检测之前&#xff0c;先要在自己的电脑上安装好终端工具和USB转串口的驱动软件。 终端工具我安装的是 MobaXterm。 USB转串口的驱…

深入理解JavaScript模块化开发

前言&#xff1a; 随着JavaScript应用程序的复杂性不断增加&#xff0c;模块化开发成为了一种必备的技术。通过将代码划分为模块&#xff0c;我们可以提高代码的可维护性、可重用性和可扩展性。在本文中&#xff0c;我们将深入探讨JavaScript模块化开发的概念、优势和不同的模块…

热门自定义报表系统推荐,哪款自定义报表系统更功能更强大?

随着企业管理的日益复杂&#xff0c;越来越多的企业需要一款高效、灵活、易用的自定义报表系统来满足其各种报表制作和数据分析需求。然而&#xff0c;在众多自定义报表系统中&#xff0c;哪款更加强大&#xff1f;今天&#xff0c;我将向大家推荐5款热门自定义报表系统&#x…

设施设备管理系统

凡尔码搭建设施设备管理系统是一种为企业和机构提供维护和管理设备、设施、建筑物和环境等设施的系统。它通过自动化设施的巡检计划、保养计划、通知和维护任务&#xff0c;使设施维护管理的工作更高效率、更科学化&#xff0c;并提高了设施设备的可靠性和使用价值。该系统具有…

asp.net学生考勤管理系统VS开发sqlserver数据库web结构c#编程Microsoft Visual Studio

一、源码特点 asp.net学生考勤管理系统 是一套完善的web设计管理系统&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为vs2010&#xff0c;数据库为sqlserver2008&#xff0c;使用c#语言开发 asp.net试卷自动生成系统VS开发sq…

谈谈 NLP中 大语言模型 LLM的In-Context Learning(ICL) 能力

In-Context Learning(ICL) 1.介绍 自GPT-3首次提出了In-Context Learning(ICL)的概念而来&#xff0c;ICL目前已经变成了一种经典的LLMs使用方法。 2.思路 ICL主要思路是&#xff0c;给出少量的标注样本&#xff0c;设计任务相关的指令形成提示模板&#xff0c;用于指导待测…