Leetcode刷题之两两交换链表中的结点和相交链表

news2024/11/25 7:09:23

只有把抱怨环境的心情,化为上进的力量,才是成功的保证。       ——罗曼·罗兰
目录

🍉一.相交链表

💐1.双指针

🍍2.计算长度加双指针

🍒二.两两交换链表中的结点 

🍌1.迭代 


🍉一.相交链表

给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。
图示两个链表在节点 c1 开始相交

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

示例 1:  

输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,6,1,8,4,5], skipA = 2, skipB = 3
输出:Intersected at '8'
解释:相交节点的值为 8 (注意,如果两个链表相交则不能为 0)。
从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,6,1,8,4,5]。
在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。
— 请注意相交节点的值不为 1,因为在链表 A 和链表 B 之中值为 1 的节点 (A 中第二个节点和 B 中第三个节点) 是不同的节点。换句话说,它们在内存中指向两个不同的位置,而链表 A 和链表 B 中值为 8 的节点 (A 中第三个节点,B 中第四个节点) 在内存中指向相同的位置。

示例 2:

输入:intersectVal = 2, listA = [1,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1
输出:Intersected at '2'
解释:相交节点的值为 2 (注意,如果两个链表相交则不能为 0)。
从各自的表头开始算起,链表 A 为 [1,9,1,2,4],链表 B 为 [3,2,4]。
在 A 中,相交节点前有 3 个节点;在 B 中,相交节点前有 1 个节点。

示例 3:

输入:intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2
输出:null
解释:从各自的表头开始算起,链表 A 为 [2,6,4],链表 B 为 [1,5]。
由于这两个链表不相交,所以 intersectVal 必须为 0,而 skipA 和 skipB 可以是任意值。
这两个链表不相交,因此返回 null 。

做题链接:相交链表

💐1.双指针

这题的目的就是找两个链表是否有公共结点,如果有公共结点就返回公共结点,如果两个链表没有公共结点即返回NULL。
我们还是使用双指针的方法,两个指针都同时指向两个链表的头结点,然后一起遍历链表。一共有三种情况。
第一种:链表没有公共结点,最好返回NULL。
第二种:链表有公共结点,且两个链表一样长,双指针同时遍历两个链表,一次性直接找到公共结点,直接返回即可。
第三种:链表有公共结点,但是两个链表不一样长,双指针一次是遍历不出来的,当一个指针把短的链表遍历完了之后,该指针直接指向长链表的头结点,然后两个指针同时走,当另一个指针走到链表的尾之后,该指针直接指向短链表的头结点,这时两个指针一起走,一定会在公共结点处相遇。关于第三种情况,可能很多人不理解,我们同时是画图来理解这里再强调一下,学习数据结构的内容一定要多画图,一定不要空想。


有了思路,我们直接写代码即可:

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    struct ListNode*pA=headA;
    struct ListNode*pB=headB;
    while(pA!=pB)
    {
        if(pA)
        {
            pA=pA->next;
        }
        else
        {
            pA=headB;//当pA走到尾,指向NULL之后,直接更新为B链表的头结点
        }
        if(pB)
        {
            pB=pB->next;//当pB走到尾,指向NULL之后,直接更新为A链表的头结点
        }
        else
        {
            pB=headA;
        }
    }
    return pB;
}

这里还有一个三目操作符的写法,思路和上述是一样的,只是代码量不一样。
三目操作符代码:

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) 
{
    if (headA == NULL || headB == NULL) {
        return NULL;
    }
    struct ListNode *pA = headA, *pB = headB;
    while (pA != pB) {
        pA = pA == NULL ? headB : pA->next;
        pB = pB == NULL ? headA : pB->next;
    }
    return pA;
}

该代码的时间复杂度为O(m+n),m和n分别是链表A和链表B的长度。两个指针都需要遍历一遍链表。 


🍍2.计算长度加双指针

刚刚那个方法更新指针的指向,其实就是把长链表多短链表那段长度给走掉,那为什么我们不能先计算两个链表的长度,然后让长的链表先走两个链表长度相减长度的绝对值,然后两个指针再同时走,如果有公共结点,直接就找到了公共结点,如果没有公共结点,两个指针同时走到两个链表的尾,返回NULL即可。(注意这题不是找值相同的结点,而是地址相同的结点)

其实这个思路是很好想的,不像第一个思路,可能稍微要难想一点。

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB)
{
    struct ListNode*pA=headA,*pB=headB;
    int lenA=1;
    int lenB=1;
    while(pA->next)
    {
        lenA++;
        pA=pA->next;
    }
    while(pB->next)
    {
        lenB++;
        pB=pB->next;
    }
    if(pA!=pB)//此时pA和pB都同时指向的尾结点,
    {         //如果最后一个结点都不相等,那么两个链表就没有公共结点
        return NULL;
    }
  int len=abs(lenA-lenB);//下面的代码就是执行有公共结点的情况

    struct ListNode*lenhead=headA;//假设A链表是长链表
    struct ListNode*shorthead=headB;
  if(lenA<lenB)//我们不知道那个链表长,需要判断一下
  {
      lenhead=headB;
      shorthead=headA;
  }
     while(len--)
     {
         lenhead=lenhead->next;
     }
     while(lenhead!=shorthead)
     {
         lenhead=lenhead->next;
         shorthead=shorthead->next;
     }
     return lenhead;
}

🍒二.两两交换链表中的结点 

给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
示例 1:
 

输入:head = [1,2,3,4]
输出:[2,1,4,3]

示例 2:

输入:head = []
输出:[]

示例 3:

输入:head = [1]
输出:[1]

🍌1.迭代 

这题就是要两两交换结点,那我们就两两交换,交换之后,我们就继续后面两个的交换,依次类推,直到把结点两两给交换完。

我们还是画图讲解:

第一步:cur->next指向next,即cur->next=next。 
 

第二步:first->next指向next->next,也就是first->next=next->next。 
第三步:next->next指向first,即next->next=first。  

 

这样我们就把前两个结点给交换了,剩下的就是写一个循环把剩下的结点两两给交换。交换两个结点之后为:
 

最后一步:这时我们只需要使cur=first,又可以继续下面两个结点的交换了,当链表结点为偶数个结点时,当cur->next=NULL时,即退出循环。当链表结点为奇数个结点时,最后一个结点也就不用交换。当cur->next->next=NULL时,即退出循环。 
直接上代码:

struct ListNode* swapPairs(struct ListNode* head){
   struct ListNode*phead=(struct ListNode*)malloc(sizeof(struct ListNode));
   phead->next=head;
   struct ListNode*cur=phead;
   while(cur->next!=NULL&&cur->next->next!=NULL)
   {
       struct ListNode*first=cur->next;
       struct ListNode*next=first->next;
       cur->next=next;
       first->next=next->next;
       next->next=first;
       cur=first;
   }
   return phead->next;
}

 

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

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

相关文章

【Golang】多线程下载器的实现

〇、前言 多线程下载&#xff0c;顾名思义就是对一个文件进行切片访问&#xff0c;等待所有的文件下载完成后在本地进行拼接成一个整体文件的过程。 因此可以利用 golang 的多协程对每个分片同步下载&#xff0c;之后再合并且进行md5校验或者总长度校验。 一、请求资源 下载…

5.7学习周报

文章目录 前言文献阅读摘要简介数据方法论预测结果结论 时间序列预测总结 前言 本周阅读文献《Water quality forecasting based on data decomposition, fuzzy clustering and deep learning neural network》&#xff0c;文献主要结合数据分解、模糊C均值聚类和双向门控循环…

设计模式 - 工厂方法模式

设计模式 - 工厂方法模式 1、关于工厂方法模式2、工厂方法模式小试牛刀2.1、类图2.2、代码清单3、工厂方法模式的扩展3.1、简单工厂模式&#xff08;静态工厂模式&#xff09; 1、关于工厂方法模式 工厂方法模式&#xff0c;就是定义一个用于创建对象的接口&#xff0c;让子类决…

Ubuntu20升级nodejs版本

执行 grunt build的时候提示node版本过低 当前版本为10.19.0&#xff0c;不满足要求 安装 n&#xff0c;用于更新 node 版本的 sudo npm install n -g用n 下载 nodejs 的最新稳定版本 sudo n stable3. 安装完毕&#xff0c;node -r检查当前版本

【算法与数据结构】链表

链表 链表&#xff1a;结构定义 链表是由一串节点串联在一起的&#xff0c;链表的每个节点存储两个信息&#xff1a;数据下一个节点的地址 分清楚两个概念&#xff1a;什么是内存内部&#xff0c;什么是程序内部 内存内部&#xff1a; 信息存储在内存空间里的 程序内部&#…

复习笔记1

考纲(张友生版本软件架构 考试题型&#xff1a; 10*3单选 5*3简答题 5*3设计图&#xff08;含画图&#xff09; 10*2 论述题 10*2综合题 复习以课件为主&#xff0c;书为辅 第一章 (软件危机) &#xff1f; &#xff1f; 构造模型与实现 掌握软件结构体系核心模型 第二章 软件体…

阿里云Alibaba Cloud Linux镜像系统介绍及常见问题解答FAQ

阿里云服务器操作系统Alibaba Cloud Linux镜像怎么样&#xff1f;可以代替CentOS吗&#xff1f;Alibaba Cloud Linux兼容性如何&#xff1f;有人维护吗&#xff1f;漏洞可以修复吗&#xff1f;Alibaba Cloud Linux完全兼容CentOS&#xff0c;并由阿里云官方免费提供长期维护。 …

Java并发,夺命 60 问

基础 1.并行跟并发有什么区别&#xff1f; 从操作系统的角度来看&#xff0c;线程是CPU分配的最小单位。 并行就是同一时刻&#xff0c;两个线程都在执行。这就要求有两个CPU去分别执行两个线程。 并发就是同一时刻&#xff0c;只有一个执行&#xff0c;但是一个时间段内&am…

linux系统中rpm与Yum软件仓库

rpm的作用&#xff1a; 在没有rpm软件管理之前我们在安装、升级、卸载服务程序时要考虑到其他程序、库的依赖关系&#xff0c;所以在进行安装、校验、卸载、升级等操作时的难度就非常之大。 rpm机制则为就是为了解决这些问题而设计的&#xff0c;rpm有点像windows系统中的控制…

xawtv涉及的vivid系统调用分析

xawtv涉及的vivid系统调用分析 文章目录 xawtv涉及的vivid系统调用分析调用过程分析摄像头驱动程序必需的11个ioctl非必须必须 分析数据的获取过程1.请求分配缓冲区: ioctl(4, VIDIOC_REQBUFS // 请求系统分配缓冲区2.查询映射缓冲区:3.把缓冲区放入队列:4.启动摄像头5.用selec…

Docker-Flannel网络讲解

目录 什么是Flannel Flannel原理 部署 环境准备 安装etcd 安装fannel 在server2上装flannel 测试 什么是Flannel flannel是 CoreOS 团队针对 Kubernetes 设计的一个覆盖网络&#xff08;Overlay Network&#xff09;工具&#xff0c;其目的在于帮助每一个使用 Kuberent…

文心一言 VS chatgpt (15)-- 算法导论3.2 4~5题

四、函数 ⌈ lg ⁡ n ⌉ ! \lceil \lg n \rceil ! ⌈lgn⌉! 多项式有界吗&#xff1f;函数 ⌈ lg ⁡ lg ⁡ n ⌉ ! \lceil \lg \lg n \rceil ! ⌈lglgn⌉! 多项式有界吗&#xff1f; 文心一言&#xff1a; chatgpt&#xff1a; 对于第一个问题&#xff0c;函数 ⌈ lg ⁡ n…

C++类和对象(6)

类和对象 1.在谈构造函数1.1. 构造函数体赋值1.2. 初始化列表1.3. explicit关键字 2. static成员2.1. 概念2.2. 特性 3.友元函数3.2.友元类 4. 内部类5.匿名对象6.拷贝对象时的一些编译器优化7.再次理解类和对象 1.在谈构造函数 1.1. 构造函数体赋值 在创建对象时&#xff0c…

【SPSS】回归分析详细操作教程(附案例实战)

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

数据结构入门-顺序表链表

线性表 线性表&#xff08;linear list&#xff09;是n个具有相同特性的数据元素的有限序列。线性表是一种实际中广泛使用多个数据结构&#xff0c;常见的线性表&#xff1a;顺序表、链表、栈、队列、字符串... 线性表在逻辑上是线性结构&#xff0c;也就说是连续的一条直线。…

前后端图片交互的简易方式

前后端图片交互的简易方式 一、交互方式说明二、前后端具体代码实现前端具体代码实现后端具体代码实现效果 测试结果 一、交互方式说明 在项目的实际开发中&#xff0c;难免会遇到前端需要渲染数据库中保存的图片&#xff0c;那咱知道图片也属于一种文件&#xff0c;不好保存到…

maven依赖jar包时版本冲突的解决

1、第一声明优先原则 在pom.xml配置文件中&#xff0c;如果有两个名称相同版本不同的依赖声明&#xff0c;那么先写的会生效。 所以&#xff0c;先声明自己要用的版本的jar包即可。 所以&#xff0c;添加新依赖时要放在最后边&#xff0c;以防止新依赖替换原有依赖造成版本冲…

Mybatis基础操作XML映射文件

Mybatis基本操作 一、环境准备 数据库表和springboot工程在课程资料中都有提供 注意&#xff0c;entrydate是用的jdk1.8中的LocalDate类型&#xff0c;createTime用的是jdk1.8中的LocalDateTime类型 二、删除 Mybatis中提供了一种参数占位符 #{id} empMapper.java package…

Leetcode461. 汉明距离

Every day a leetcode 题目来源&#xff1a;461. 汉明距离 解法1&#xff1a;模拟 先将x和y转为为对应二进制的字符串&#xff0c;再遍历两个字符串进行比较。 代码&#xff1a; /** lc appleetcode.cn id461 langcpp** [461] 汉明距离*/// lc codestart class Solution {…

HTML的两个实战项目

文章目录 HTML的两个实战项目1. 个人简历1. 1 快速生成模板1.2 根据简历格式进行预设计1.3 开始创作吧1.3.1 基本信息1.3.2 教育背景1.3.3 专业技能1.3.4 我的项目1.3.5 自我评价 2. 输入简历信息页面设计2.1 设计大概框架2.2 开始创作吧2.2.1 输入姓名2.2.2 上传照片2.2.3 输入…