C++刷题第四天 链表 24. 两两交换链表中的节点 ● 19.删除链表的倒数第N个节点 ● 160. 链表相交 ● 142.环形链表II

news2024/11/14 20:40:49

24. 两两交换链表中的节点

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

示例:

原列表为:1-2-3-4-5

交换一次后为:2-1-3-4-5

交换结束为:2-1-4-3-5

 就是下标为偶数的节点与后一节点交换位置

解题思路:

 如图所示,先把cur指针域指向2,再把2指针域指向1,最后1指针域指向3,完成这一交换;但是实际写代码过程中,因为链表的特性,要考虑实施过程中每个节点指向的变化。

在步骤一执行后,节点1如果不预先存储给其他临时节点,节点1就找不到了;

执行完步骤二,节点3的位置也是无法直接寻得的,也需要临时节点存储节点3;

并且整个循环的截止条件是什么?

当链表节点总数为奇数时,最后一个节点保持不动,那cur的位置就是倒数第二个节点,判断条件为cur->next->next != nullptr;

当链表节点数为偶数时,所有节点完成替换,cur为最后一个节点,判断条件为cur->next != nullptr;

整个交换过程完成后,返回的应该是虚拟头节点dummyhead->next。

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        ListNode*dummyhead = new ListNode(0);
        dummyhead->next = head;
        ListNode*cur = dummyhead;
        while(cur->next != nullptr && cur->next->next != nullptr) {
            ListNode* tmp = cur->next; // 记录临时节点
            ListNode* tmp1 = cur->next->next->next; // 记录临时节点

            cur->next = cur->next->next;    // 步骤一
            cur->next->next = tmp;          // 步骤二
            cur->next->next->next = tmp1;   // 步骤三

            cur = cur->next->next; // cur移动两位,准备下一轮交换
        }
        return dummyhead->next;
    }
};

19.删除链表的倒数第N个节点

给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。

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


示例 2:

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


示例 3:

输入:head = [1,2], n = 1
输出:[1]

解题思路:双指针法

限定条件一:

用两个指针,一快一慢,快指针慢指针初始为同一位置后,快节点先移动n步,然后再同时移动快慢指针直到快指针节点的指针域指向空,这时,慢指针的next就是倒数第n个节点,将slow->next = slow->next->next即可。

避坑:

1、快慢指针初始位置应该是什么呢?

如果都初始为头节点,那如示例二,就没有办法完成任务了。所以要使用虚拟头节点,在头节点前面增加一个临时节点,指向头节点,并且将快慢指针都是初始化为该虚拟头节点,可以避免示例二的情况。

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode*dummyhead = new ListNode(0);
        dummyhead->next = head;
        ListNode*fast = dummyhead;
        ListNode*slow = dummyhead;
        while(n-- && fast != NULL){
            fast = fast->next;
        }
        
        while(fast->next != nullptr){
            fast = fast->next;
            slow = slow->next;
        }
        ListNode*temp = slow->next;
        slow->next = slow->next->next;
        delete temp;
        return dummyhead->next;
    }
};

限定条件二:

其实这里有另外一套限定条件,如下:

用两个指针,一快一慢,快指针慢指针初始为虚拟头节点,快节点先移动n+1步,然后再同时移动快慢指针直到快指针节点为空,这时,慢指针的next就是倒数第n个节点,将slow->next = slow->next->next即可。

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* dummyHead = new ListNode(0);
        dummyHead->next = head;
        ListNode* slow = dummyHead;
        ListNode* fast = dummyHead;
        while(n-- && fast != NULL) {
            fast = fast->next;
        }
        fast = fast->next; // fast再提前走一步,因为需要让slow指向删除节点的上一个节点
        //也可以在前方定义fast时将fast定义为head节点
        while (fast != NULL) {
            fast = fast->next;
            slow = slow->next;
        }
        slow->next = slow->next->next; 
        
        // ListNode *tmp = slow->next;  C++释放内存的逻辑
        // slow->next = tmp->next;
        // delete nth;
        
        return dummyHead->next;
    }
};

160. 相交链表

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

图示两个链表在节点 c1 开始相交:

示例一:

输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,6,1,8,4,5], skipA = 2, skipB = 3
输出:Intersected at '8'

示例二:

输入:intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2
输出:null

解题思路:

如果两个链表在节点E相交,那么E之后的节点肯定都是相同的,所以可以考虑求出两个链表的长度,然后计算长度差值,然后让curA移动到,和curB 末尾对齐的位置,如图:

 

 然后从此处开始对比curA和curB,如果两个节点相同,那么此节点就是两链表相交的节点。

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        int m=0,n=0;
        ListNode*cura = headA;
        while(cura){   //计算链表A的长度
            m++;
            cura = cura->next;
        }
        ListNode*curb = headB;
        while(curb){     //计算链表B的长度
            n++;
            curb = curb->next;
        } 
        cura = headA;
        curb = headB;
        if(m>n){            //如果A较长,那移动cura到与curb同长的位置
            int x = m-n;
            while(x-- > 0){
                cura = cura->next;
            }
        }
        else{           //如果B较长,将curb移动到与cura同长度的位置,如果A=B,那么X=0,不会进行任何操作
            int x = n-m;
            while(x-- > 0){
                curb = curb->next;
            }
        }
        while(cura != NULL){      //然后同时移动cura和curb,直到cura=curb,返回当前节点
            if(cura == curb ){
                return cura;
            }
            cura = cura->next;
            curb = curb->next;
        }
        return NULL;       //如果在上个while循环没有return,那么就没有找到相交节点,return null
    }
};

142.环形链表II 

给定一个链表的头节点  head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null

 解题思路:

 这题相对来说解题思想比较重要,知道这个思想后,代码并不复杂,这个解题思路建议看这个:代码随想录 (programmercarl.com)

讲解的很详细。

整体过程就是用两个指针,一快一慢,然后快指针一次移动两位,慢指针一次移动一位,如果有环,那么快慢指针一定会在环内某个节点相遇,因为只要慢指针入环,那快指针相对于慢指针就是每次循环靠近慢指针一次,所以只要在环内,就肯定会相遇并且是在慢指针在环内循环一遍之前。

快慢指针相遇就代表有环,那么怎么找到环的入口呢?定义一个新的节点等于快慢指针相遇的节点,另外一个新节点等于头节点,然后两个节点同时向后移动,直到相遇,这个相遇的节点就是环的入口。详细原理可以看上面详解的链接。

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode* fast = head;
        ListNode* slow = head;
        while(fast != NULL && fast->next != NULL){
            fast = fast->next->next;
            slow = slow->next;
            if (fast == slow){
                ListNode* p = fast;
                ListNode* q = head;
                while(p != q){
                    p = p->next;
                    q = q->next;
                }
                return p;
            }
        }
        return NULL;
    }
};

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

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

相关文章

【Mysql】Explain深入分析(三)

Explain工具介绍 使用EXPLAIN关键字可以模拟优化器执行SQL语句,分析你的查询语句或是结构的性能瓶颈 在 select 语句之前增加 explain 关键字,MySQL 会在查询上设置一个标记,执行查询会返回执行计划的信息,而不是执行这条SQL 注意…

node ffmpeg jsmpeg 拉流 展示笔记

拉流参考上一篇 基础:FFmpeg安装过 拉流完成之后转换成可播放的方式 1、下载jsmpeghttps://github.com/phoboslab/jsmpeg 下载完 用vscode 打开jsmpeg-master目录 2、在根目录下安装 node-media-server npm install node-media-server 新建app.js并运行 const…

8 图像去噪 滤波 锐化 边缘检测案例(matlab程序)

1.简述 学习目标:一个图像处理的经典综合案例 一、图像锐化的原理   图像锐化的目的是凸显物体的细节轮廓,通常可以用梯度、Laplace算子和高通滤波来实现,下面一一说明: 1、梯度法 梯度计算可以参考 小白学习图像处理——cann…

数据可视化01_t-SNE

1. t-SNE的定义 t-SNE stands for t-distributed Stochastic Neighbor Embedding. 代表 t 分布随机邻域嵌入。 t-SNE 获取高维数据并将其降低到较低维空间,同时保持数据点之间的关系尽可能接近其原始排列。 它是一种无监督机器学习算法,由 Laurens va…

8年测试经验总结,性能测试流程与性能测试学习路线,卷起来...

目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 性能测试流程 1、…

运输层概述、端口号、复用与分用

1.运输层概述、端口号、复用与分用 笔记来源: 湖科大教书匠:运输层概述 湖科大教书匠:运输层端口号、复用与分用的概念 声明:该学习笔记来自湖科大教书匠,笔记仅做学习参考 1.1 运输层概述 计算机网络体系结构中的物…

交流220v转12v给单片机供电芯片

客户的应用需求:AD220V转DC12V 体积要非常小,单片机使用,单片机设备12V 电流很小不会超过100mA? 【AD220V转DC12V体积小的问题】 问题:我需要将交流电(220V)转换为直流电(12V&…

fastadmin后台 点击开关 弹出 你没有权限访问 角色组里面添加了,除了超级管理员其他的只要用状态开关就,没权限 解决办法

首发地址:https://ask.fastadmin.net/question/22863.html 然后再对应的后台控制器里面 加入 protected $multiFields 你设计数据库的开关字段; //注意是字段,不是填写: multi 示例: protected $multiFields show_switch; 也可以多个 p…

QWebEngine应用(一)

前言 很早以前就听说过Qt也能显示网页,一直没有机会真正研究应用起来,刚好最近项目中使用到了QWebEngine内嵌浏览器打开第三方的网站,使用的Qt版本为5.15,踩了不少的坑,这里做个总结。 QWebEngine架构 Qt WebEngine…

亚马逊云科技连续12年被评为“领导者”,用实力赋能企业出海

从人类发展历史上看,无论是刳木为舟,剡木为楫,还是郑和下西洋,亦或是欧洲大航海时代,人类对于出海探索这件事就从未停止。而在如今的时代,相似的故事依旧在上演。过去的十年,是中国互联网最为繁…

多路码流RTSP传输并对每路视频图像叠加OSD信息

一、先保证多路视频码流保存到本地,并且分辨率正确 注意点: 1.VPSS分两路通道 2.VENC分两路通道 if(s32ChnNum>1) {s32Ret SAMPLE_COMM_SYS_GetPicSize(gs_enNorm, enSize[0], &stSize);if (HI_SUCCESS ! s32Ret){SAMPLE_PRT("SAMPLE_COM…

下载网页视频的软件 下载网页视频的方法

视频已然成为一种非常有力的展示方式,我们想要下载视频内容,需要用到下载网页视频的软件,如今这类软件有很多。下载网页视频的方法,也因为使用的软件不同,方法各异。下面我们就来看详细介绍吧! 一、下载网…

【DC-DC】AP9196 DC-DC升压恒流电源管理芯片 升降压3-12V输出9V LED驱动方案

1,方案;升降压3-12V输出9V LED驱动方案BOM表 ​ 2,方案;升降压3-12V输出9V LED驱动方案线路图 3,产品说明 AP9196 是一系列外围电路简洁的宽调光比升压调光恒流驱动器,适用于 3-40V 输入电压范围的 LED照明领域。AP9196 采用我…

Leveldb代码阅读笔记

整体架构 如上图,leveldb的数据存储在内存以及磁盘上,其中: memtable:存储在内存中的数据,使用skiplist实现。immutable memtable:与memtable一样,只不过这个memtable不能再进行修改&#xff0…

使用模拟电路制造CPU——从硬件到软件的设计

计算机中蕴藏的哲理 最基本的思想是:通过基本电路的接线,确立输入-输出规则,类似函数的入参和返回值,便构成一个功能电路单元。单元套单元组成新单元,如此往复。“一生二,二生三,三生万物”。这…

盒马上市,即时零售最大“变量”

若盒马年内成功上市,等待完成下一轮融资的朴朴超市的处境恐将更加尴尬,另区域性中小商超或将迎来新一轮倒闭潮。 疫情过后,国内消费市场一直处于走弱态势。据商务大数据监测,今年端午假期,部分地区零售和餐饮数据远不及…

数据结构记录和leetcode刷题记录

背景 时间复杂度 算法的执行时间与输入值之间的关系。 参考:算法中七种常见的时间复杂度 - 掘金 参考视频:1. 算法的时间复杂度_哔哩哔哩_bilibili 空间复杂度 算法的存储空间与输入值之间的关系。 参考:2. 算法的空间复杂度_哔哩哔哩_bili…

【花雕】全国青少年机器人技术一级考试备考实操搭建手册1

目录 1、秋千 2、跷跷板 3、搅拌器 4、奇怪的钟 5、起重机 6、烤肉架 7、手摇风扇 8、履带车 9、直升机 10、后轮驱动车 秋千 (闽南语、广东话称千秋)是一种座椅,常见于儿童游乐场、杂技演员马戏团或门廊上放松的地方。 秋千的座位通常悬挂在…

蘑菇街被裁后,成功入职字节跳动的那一天,我哭了...

前言 先说一下个人情况,18 届应届生,通过校招进入到了蘑菇街,然后一待就待了差不多 2 年多的时间,可惜的是今年 4 月份受疫情影响遇到了大裁员,而他也是其中一员。好在早有预感,提前做了准备,之…

C++primer(第五版)第九章(顺序容器)

简单来说存入顺序和取出顺序一致的容器被称为顺序容器. 9.1顺序容器概述 vector和string将元素保存在连续的内存空间中,所以每次添加或删除元素都会非常耗时,但是通过下标计算内存地址来读取元素是非常快的. list和forward_list为链表,添加或删除元素的操作很快,但是不支持元…