每日一题--相交链表

离思五首-元稹

曾经沧海难为水,除却巫山不是云。
取次花丛懒回顾,半缘修道半缘君。

目录

题目描述:

思路分析:

方法及时间复杂度:

法一 计算链表长度(暴力解法)

法二 栈

法三 哈希集合

法四 map或unordered_map

法五 双指针(经典解法)

法六 递归(烧脑解法)

个人总结


题目描述:

相交返回相交结点,不相交返回

160. 相交链表 - 力扣(LeetCode)

思路分析:

要找相交的那个结点,可以让两个起始位置相同的指针遍历两个链表,当指针所指结点位置相同时,就是相交结点。简单粗暴。

 也可以用哈希,栈等方法,详情如下。

方法及时间复杂度:

法一 计算链表长度(暴力解法)

计算两个链表长度m,n。再定义两个指针,要使两个指针在同一起始位置,需要使长链表的那个指针那个先走abs(m-n)步

 双指针同时走,相同则为相交。否则同时走到空。代码如下:

class Solution {
public:ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {int lenA=0,lenB=0;ListNode* cur=headA;while(cur){++lenA;cur=cur->next;}cur=headB;while(cur){++lenB;cur=cur->next;}int gap=abs(lenA-lenB);//两链表的差距ListNode* fast=nullptr,*slow=nullptr;if(lenA>lenB){fast=headA;slow=headB;}else{fast=headB;slow=headA;}while(gap--){fast=fast->next;//fast先走gap步}while(fast){if(fast==slow){return fast;}fast=fast->next;slow=slow->next;}return nullptr;}
};

时间复杂度O(m+n),m,n为两个链表长度

空间复杂度O(1)

法二 栈

设两个栈,将两个链表的结点分别入栈,依次访问栈顶元素,如果相交,则栈顶元素相等的最后一个结点为相交结点。不相交说明栈顶元素不相同,直接返回空。

 代码如下:

class Solution {
public:ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {stack<ListNode*> stA,stB;ListNode* cur=headA;while(cur){stA.emplace(cur);cur=cur->next;}cur=headB;while(cur){stB.emplace(cur);cur=cur->next;}while(!stA.empty()&&!stB.empty()&&stA.top()==stB.top()){cur=stA.top();stA.pop();stB.pop();}return cur;}
};

时间复杂度O(m+n)

空间复杂度O(m+n)

法三 哈希集合

将第一个链表放入集合中,在遍历第二个链表的结点,然后在集合中查找,如果查找到的第一个结点,就是相交结点,直接返回,否则返回空。代码如下:

class Solution {
public:ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {unordered_set<ListNode*> hash;ListNode* cur=headA;while(cur){hash.insert(cur);cur=cur->next;}cur=headB;while(cur){if(hash.find(cur)!=hash.end()){return cur;}cur=cur->next;}return nullptr;}
};

时间复杂度O(m+n)

空间复杂度O(m)

法四 map或unordered_map

与法三思路相同,都用的是这几个容器的查找功能,不多解释。

class Solution {
public:ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {unordered_map<ListNode*, int> hash;ListNode* cur = headA;while (cur) {hash[cur]++;cur = cur->next;}    cur = headB;while (cur) {if (hash.find(cur) != hash.end()) {return cur;}cur = cur->next;}return nullptr;}
};

时间复杂度O(m+n)

空间复杂度O(m)

 map还可以这样:

class Solution {
public:ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {map<ListNode*,int> nodes;ListNode* cur=headA;while(cur){nodes[cur]++;cur=cur->next;}cur=headB;while(cur){nodes[cur]++;cur=cur->next;}for(auto node:nodes){if(node.second==2){return node.first;}}return nullptr;}
};

时间复杂度O(m+n)

空间复杂度O(m+n)

法五 双指针(经典解法)

 "来时路上不见你,于是便走你来时的路,相遇时才发现你也走过我曾走过的路💓"

class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {ListNode *Girl = headA, *Boy = headB;while (Girl!=Boy) {Girl=Girl==nullptr ? headB:Girl->next;Boy = Boy==nullptr ? headA:Boy->next;}return Boy;}
};

时间复杂度O(m+n)

空间复杂度O(1)

利用抽象思维和数学思维,可以将两条链表连接成一条带环链表,让两个指针同时走,环的入口就是相交结点,相逢何必曾相识,同是天涯沦落人,相交就一定会相逢,不相交都走向空。

原理:两指针相遇时,走的距离是相同的。设两条链表未相交部分长度为a,b。相交部分的长度为c。则有a+c+b==b+c+a。当一指针走向空时,则走到另一个链表的开始。

 

法六 递归(烧脑解法)

首先定义一个递归函数`dfs`,该函数接收3个指针参数:指向链表A当前节点的指针`curA`,指向链表B当前节点的指针`curB`,以及链表B的头节点指针`headB`。 

如果A链表和B链表相交,即相交节点之后的节点全部相同,则直接返回相交节点  `(curA==curB)`,表示两个指针指向的节点相同,那么这个节点就是相交节点,直接返回即可。

如果两个指针都没有遍历到链表的结尾,则继续往下遍历,即更新指向链表B节点的指针,直到有一个链表遍历结束,进入下一步操作。

如果B链表已经到达了链表末尾,那么就把`curB`指针指向 `headB`,即链表B的头节点,同时把`curA`指针指向下一个节点,继续查找。这样做的本质是相当于把链表B的指针接到了链表A上,形成了一条新的链表,重新遍历该新链表是否存在相交节点。

如果A链表已经到达了链表末尾,那么就把`curA`指针指向`headB`,即链表B的头节点,同时把`curB`指针指向下一个节点,继续查找。这样做的本质也是相当于把链表A的指针接到了链表B上,形成了一条新的链表,重新遍历该新链表是否存在相交节点。

如果上面的步骤都没有找到相交节点,则表明两个链表不相交,返回空指针即可。

最后,在`getIntersectionNode`函数中,调用`dfs`递归函数,传入链表A的头节点`headA`,链表B的头节点`headB`,以及链表B的头节点指针`headBref`,作为参数。函数返回的即为两个链表的相交节点。代码如下:

struct ListNode *dfs(struct ListNode *curA, struct ListNode *curB,struct ListNode *headB){if(curA==curB){return curB;}if(curA!=NULL&&curB!=NULL){return dfs(curA,curB->next,headB);}else if(curB==NULL&&curA!=NULL){return dfs(curA->next,headB,headB);}else{return NULL;}
}
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {return dfs(headA,headB,headB);
}

时间复杂度O(m+n)

空间复杂度O(max(m,n))

用c++超时,用c语言不会。毕竟c语言是世界上最好的语言。

个人总结

俗话说,温故而知新。第一次看这道题时,没有想到那么多解法。随着知识面的扩张,对旧的东西又有了新的感悟。

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

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

相关文章

【面经八股】搜广推方向:常见面试题(二)

【面经&八股】搜广推方向:常见面试题(二) 文章目录 【面经&八股】搜广推方向:常见面试题(二)1. FTRL 是什么?(Follow The Regularized Leader)2. 梯度下降方法3. 推荐系统中常见的Embedding方法有哪些?4. Embedding与推荐系统有哪些结合5. FM 和 FFM6. FNN7. 深…

一文学会使用React-Router v6

文章目录 基本格式createBrowserRouterType Declarationroutesbasenamefuture and window ... 省略 <RouterProvider>fall上述文本提到 createBrowserRouter 函数的一个特性&#xff1a;在非服务器端渲染应用程序时&#xff0c;当它挂载时会初始化所有匹配的路由加载器。…

解决hbuilder使用android studio模拟器不能热更新

hbuilder使用android studio模拟器编&#xff0c;在编写代码时&#xff0c;不能热更新&#xff0c;总是需要重启虚拟机中的程序&#xff0c;hbuilderx的版本是3.1.22&#xff0c;android studio的版本是4.2.2 同时在hbuilderx中出现如下报错信息&#xff1a; 报错信息&#x…

HuggingFace学习笔记--AutoModel的使用

1--AutoModel的使用 官方文档 AutoModel 用于加载模型&#xff1b; 1-1--简单Demo 测试代码&#xff1a; from transformers import AutoTokenizer, AutoModelif __name__ "__main__":checkpoint "distilbert-base-uncased-finetuned-sst-2-english"t…

java进阶---多态

多态的概述 什么是多态 同一个对象,在不同时刻表现出来的不同形态 多态的前提 要有继承或实现关系要有方法的重写要有父类引用指向子类对象 多态的具体实现 对象的多态是多态的核心和重点 规则: 一个对象的编译类型与运行类型可以不一致编译类型在定义对象时,就确定了,…

三数之和问题

给你一个整数数组 nums &#xff0c;判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k &#xff0c;同时还满足 nums[i] nums[j] nums[k] 0 。请 你返回所有和为 0 且不重复的三元组。 注意&#xff1a;答案中不可以包含重复的三元组。 示例 1&…

【笔记 Pytorch 08】深度学习模板 (未完)

文章目录 一、声明二、工程结构三、文件内容main.pymodel.pydataset.pyutils.py 四、问题汇总 一、声明 非常感谢这些资料的作者&#xff1a; 【参考1】、【PyTorch速成教程 (by Sung Kim)】 二、工程结构 ├── main.py&#xff1a;实现训练 (train) 、验证(validation)和…

python pip安装第三方包时报错 error: Microsoft Visual C++ 14.0 or greater is required.

文章目录 1.问题2.原因3.解决办法 1.问题 pip install 的时候报错一大堆&#xff0c;其中有这么一段话 &#x1f447; error: Microsoft Visual C 14.0 or greater is required. Get it with "Microsoft C Build Tools": https://visualstudio.microsoft.com/visua…

rdf-file:读和写

<dependency><groupId>com.alipay.rdf.file</groupId><artifactId>rdf-file-core</artifactId><version>2.2.10</version> </dependency>一&#xff1a;读 一&#xff1a;写 写文件之正常写 协议布局模板 使用内置的布局文…

二分 模板

好久没更新博客了&#xff0c;之前一直在准备比赛&#xff0c;忙着学算法和写题&#xff0c;今天写了一道二分答案的题&#xff0c;发现之前那种二分写法有一丢丢的问题&#xff0c;导致有道题只能过97%的点。 emmm,还是把最经典的二分的板子写在这记录下&#xff08;这里参考…

python每日一题——8无重复字符的最长子串

题目 给定一个字符串 s &#xff0c;请你找出其中不含有重复字符的 最长子串 的长度。 示例 1: 输入: s “abcabcbb” 输出: 3 解释: 因为无重复字符的最长子串是 “abc”&#xff0c;所以其长度为 3。 示例 2: 输入: s “bbbbb” 输出: 1 解释: 因为无重复字符的最长子串…

精进Beautiful Soup 小技巧(二)---处理多种页面结构

前言: 为了处理多种不同结构的页面&#xff0c;一个灵活的代码基础是至关重要的。一些针对性的技巧和方法&#xff0c;让你能够优雅地解决遇到的页面结构多元化的问题。 使用条件语句适配不同布局 当面对页面布局差异时&#xff0c;选择合适的条件语句至关重要。 认识布局类型…

正则表达式例题-PTA

PTA-7-55 判断指定字符串是否合法-CSDN博客 7-54 StringBuffer-拼接字符串 题目&#xff1a; 输入3个整数n、begin、end。 将从0到n-1的数字拼接为字符串str。如&#xff0c;n12&#xff0c;则拼接出来的字符串为&#xff1a;01234567891011 最后截取字符串str从begin到end(包…

【2023 年终盘点】今年用的最多的 10 款浏览器插件

分享顺哥今年用的最多的 10 款浏览器插件。 排名不分先后,涉及各个方面的应用。 大家有好用的插件也欢迎在评论区留言分享! 视频 YouTube:https://youtu.be/ZpTydUSBwCA 顺哥博客 浏览器扩展篇 注意: 1、以下介绍的均为在 Google Chrome 浏览器适用的小插件,部分插件…

2018年11月8日 Go生态洞察:参与2018年Go用户调查

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

一个通用的分页实体对象的思考

背景 用得非常多的一个分页实体对象 说明 只是一种抽象的思路, 可能不一定能够直接使用, 慎用. 只是一种抽象的思路, 可能不一定能够直接使用, 慎用. 只是一种抽象的思路, 可能不一定能够直接使用, 慎用. 分页实体 Data public class PageEntity<T> {/*** 分页后的结…

文件解析工具

前言 对Excel & CSV 文件解析 package com.wind.bird.Utils;import com.opencsv.CSVReader; import com.opencsv.CSVReaderBuilder; import org.apache.commons.validator.Var; import org.apache.poi.hssf.usermodel.HSSFCell; import org.apache.poi.hssf.usermodel.HS…

基于springboot学籍管理系统

一、设计目的 1. 复习、巩固Java语言的基础知识&#xff0c;进一步加深对Java语言的理解和掌握&#xff1b; 2. 课程设计为学生提供了一个既动手又动脑&#xff0c;独立实践的机会&#xff0c;将课本上的理论知识和实际有机的结合起来&#xff0c;锻炼学生的分析解决实际问题…

2016年五一杯数学建模B题能源总量控制下的城市工业企业协调发展问题解题全过程文档及程序

2016年五一杯数学建模 B题 能源总量控制下的城市工业企业协调发展问题 原题再现 能源是国民经济的重要物质基础,是工业企业发展的动力&#xff0c;但是过度的能源消耗&#xff0c;会破坏资源和环境&#xff0c;不利于经济的可持续发展。目前我国正处于经济转型的关键时期&…

关于 raw 图像的理解

1、问题背景 在图像调试过程&#xff0c;当发现一个问题时&#xff0c;很多时候都要通过 dump raw图像来分析&#xff0c;如果raw图像上有&#xff0c;那就排除了是 ISP的处理导致。 下一步就是排查 sensor 或者镜头&#xff0c;这样可以有效的帮我们定位问题所在。 但遇到过…