代码随想录算法训练营第四天 | 24. 两两交换链表中的节点 19.删除链表的倒数第N个节点 面试题 02.07. 链表相交 142.环形链表II

news2024/11/24 17:46:29

今天是链表章节最后一天,加油💪

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

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

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

示例 2:
输入:head = []
输出:[]

示例 3:
输入:head = [1]
输出:[1]


思路:本题需要借助几个临时节点完成交换,想要两辆交换节点,必须有临时节点保存第三个节点。假设前三个节点A、B、C,要交换AB节点的位置,需要新建一个虚拟头节点,并用指针curr指向虚拟头节点,用临时节点temp记录节点A,临时节点1temp1记录节点C,交换代码就是curr->next = curr->next->next; curr->next->next = temp; curr->next->next->next = temp1;也就是head->next = B; B->next = A; A->next = C;(交换代码的含义,不能直接用这个,注意链表节点交换时,要提前保存next指针指向的下一个节点,不然容易丢失下一个节点)

C++版本

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        ListNode *head_ = new ListNode(0, head);
        ListNode *curr = head_;
        while (curr->next != 0 && curr->next->next != 0) { // 顺序不能颠倒,不然会出现空指针异常
            ListNode *temp = curr->next;
            ListNode *temp1 = curr->next->next->next;
			
			// 主要交换代码
            curr->next = curr->next->next;
            curr->next->next = temp;
            curr->next->next->next = temp1;

            curr = curr->next->next;
        }
        return head_->next;
    }
};

这题不算难,就是要注意一些细节的问题。


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

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

示例 1:
输入: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个节点,不要看错题目要求了!这题我写了两种方法,一种是直接法,首先遍历一遍链表算出链表长度以及倒数第n个节点属于正数第几个节点,然后再遍历一次找到要删除的节点的前一个节点,最后进行删除操作;另一种是利用快慢指针,双指针的方法实在是太妙了,令快慢指针都指向虚拟头节点,快指针先走n步,然后快慢指针再同时往前走,当快指针走到链表的最后一个节点时,慢指针正好在倒数第n+1个节点,便可进行删除操作。

C++版直接方法

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {  //删除倒数第n个
        ListNode *head_ = new ListNode(0, head);  // 创建一个虚拟头节点
        ListNode *curr = head_;
        ListNode *temp = head_;
        int l = 0; int t;  // 
        while (temp != NULL) {  // 计算链表长度(从1开始)
            temp = temp->next;
            l++;
            t = l - n;  // 计算循环次数
        }
        while (--t) {
            curr = curr->next;  // 遍历到需要删掉的节点的上一个节点
        }
        curr->next = curr->next->next;
        return head_->next;
    }
};

C++版双指针

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode *head_ = new ListNode(0, head);
        ListNode *fast = head_;
        ListNode *slow = head_;
        while (n-- && fast != NULL) {
            fast = fast->next;  // fast先走n步
        }
        while (fast->next != NULL) {
            fast = fast->next;  // 当fast走到最后一个节点时
            slow = slow->next;  // slow走到倒数第n个节点的前一个节点?
        }
        slow->next = slow->next->next;
        return head_->next;
    }
};

一定要掌握双指针方法的核心思想,并学会灵活应用!太好用了!


面试题 02.07. 链表相交

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

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

注意,函数返回结果后,链表必须 保持其原始结构 。

示例 1:

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

解释:相交节点的值为 8 (注意,如果两个链表相交则不能为 0)。
从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,0,1,8,4,5]。
在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。


思路:注意不是数值相等算相交,是节点一样才算相交,这题我一开始没有什么思路,看了Carl哥的视频茅塞顿开!首先要明确,从相交的节点开始,后面的节点都是一样的,直到结束。这可不是一句废话,这是解题的关键。所以将两个链表末尾对齐,从后半部分找重合的节点即可。

C++版本

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode *head_A = new ListNode(0, headA);
        ListNode *head_B = new ListNode(0, headB);
        ListNode *curr_A = head_A;
        ListNode *curr_B = head_B;
        int len_A = 0; int len_B = 0;
        while (curr_A->next != 0) {  // 计算链表A的长度
            len_A++;
            curr_A = curr_A->next;
        }
        while (curr_B->next != 0) {  // 计算链表B的长度
            len_B++;
            curr_B = curr_B->next;
        }
        curr_A = head_A;
        curr_B = head_B;
        if (len_B > len_A) {  // 保证最长的是链表A
            swap (curr_A, curr_B);
            swap (len_A, len_B);
        }
        int t = len_A - len_B;  // 将两链表末尾对齐,curr_A需要移动的次数
        while (t--) {
            curr_A = curr_A->next;
        }
        while (curr_A !=NULL) {
            if (curr_A == curr_B) {
                return curr_A;  // 一个一个的返回重合的节点
            }
            curr_A = curr_A->next;
            curr_B = curr_B->next;
        }
        return NULL;
    }
};

这里的一个小tips是,将长链表放在curr_A,将短链表放在curr_B,方便了后续的操作。


142.环形链表II

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

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

不允许修改 链表
示例 1:
输入:head = [3,2,0,-4], pos = 1
输出:返回索引为 1 的链表节点
解释:链表中有一个环,其尾部连接到第二个节点。

示例 2:
输入:head = [1,2], pos = 0
输出:返回索引为 0 的链表节点
解释:链表中有一个环,其尾部连接到第一个节点。

示例 3:
输入:head = [1], pos = -1
输出:返回 null
解释:链表中没有环。


思路:不得不感叹双指针是真好用。本题需要一定的数学证明,详情请见代码随想录。本题第一步判断是否有环,第二步找环的入口。第一步:快指针一次走两步,慢指针一次走一步,当两指针相遇说明一定有环。第二步:令快指针起点为相遇点,慢指针起点为头节点,两指针每次都只走一步,下次相遇一定是在环的入口。具体证明见上述链接。

C++版本

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode *fast = head;
        ListNode *slow = head;
        while (fast != 0 && fast->next != 0) {  // 快指针走两步,慢指针走一步
            fast = fast->next->next;
            slow = slow->next;
            if (fast == slow) {  // 快慢指针相遇,不能直接break,不然无法判断无环的情况
                ListNode *index_f = fast;  // 重新赋值index_f指针指向相遇点
                ListNode *index_h = head;  // 另一个index_h指针指向头节点
                while (index_f != index_h) {  // 再次相遇的点就是环的入口
                    index_f = index_f->next;
                    index_h = index_h->next;
                }
                return index_f;
            }
        } 
        return NULL;  // 遍历结束快慢指针都没有相遇过,就没有环
    }
};

其实本题也可以采用 19.删除链表的倒数第N个节点 类似的思路,在找到相遇点后,让快指针绕环走一圈,计算出环的长度L;再将快慢指针重新指向头节点,这次让快指针先走L步,慢指针再和快指针一起移动,每次移动一步;因为快指针比慢指针多走了一个环的距离,所以下一次相遇一定是在环的入口!

这是训练营小伙伴 芒果冰冰 的解法,大家都很棒!像大家学习,加油💪

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

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

相关文章

html练习11:案例仿制

1.目标效果 2.布局效果 3.顶端部分制作效果 问题:img和p无法同时垂直居中显示,img会顶端对齐,p会底部对齐 解决方法:把img作为背景加入;用两个div分别做img和p的容器再进行格式调整 4.导航栏部分制作效果 要点&#…

保证项目如期上线,测试人能做些什么?

要保证项目按照正常进度发布,需要整个研发团队齐心协力。 有很多原因都可能会造成项目延期。 1、产品经理频繁修改需求 2、开发团队存在技术难题 3、测试团队测不完 今天我想跟大家聊一下,测试团队如何保证项目按期上线,以及在这个过程中可能…

词法分析程序

一、实验原理 1.1实验内容 通过本实验,应达到以下目标: 1.掌握从源程序文件中读取有效字符的方法和产生源程序的内部表示文件的方法。 2.掌握词法分析的实现方法。 3.上机调试编出的词法分析程序。 1.2实验内容 词法分析是作为相对独立的阶段来完成的…

C# 事件

一 C#中的事件 大致上:事件-----回调函数; 二 用户界面中的事件 ① 按钮点击事件 ② 基本的写法 this.button1.Clicknew System.EventHandler(this.button1_Click); private void button1_Click(object sender,EventHandler e) {this.label1.TextDat…

C++智能指针weak_ptr

C智能指针weak_ptr 学习路线:C智能指针shared_ptr->C智能指针unique_ptr->C智能指针weak_ptr 简介:本文讲解常用的智能指针的用法和原理,包括shared_ptr,unique_ptr,weak_ptr。 概述 weak_ptr设计的目的是为配合 shared_ptr 而引入…

静电场方程与边界面上的衔接条件 工程电磁学 P6

我们现在已经知道两个公式 我们可以得到微分形式 对于体密度,面密度,线密度,点电荷的理解 很多同学会问空间中为什么要有面密度,线密度的存在呢? 其实这个是模型的需要,因为介质不一定是连续的&#xff0…

如何设计一个高性能的图 Schema

本文整理自青藤云安全工程师——文洲在青藤云技术团队内部分享,分享视频参考:https://www.bilibili.com/video/BV1r64y1R72i 图数据库的性能和 schema 的设计息息相关,但是 NebulaGraph 官方本身对图 schema 的设计其实没有一个定论&#xff…

Codeforces Round #837 (Div. 2) C. Hossam and Trainees

Problem - C - Codeforces 翻译: 胡萨姆有𝑛名学员。他给𝑖-th的学员分配了一个号码𝑎𝑖。 一双𝑖-th和𝑗-th(𝑖≠𝑗)学员被称为成功的如果有一个整数𝑥(&…

基于springboot的企业员工工资管理系统(财务系统)

项目描述 临近学期结束,还是毕业设计,你还在做java程序网络编程,期末作业,老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下,你想解决的问…

Vue渲染器(二):挂载与更新

渲染器(二):挂载与更新 前面介绍了渲染器的基本概念和整体框架,接下来就可以介绍渲染器的核心功能:挂载与更新。 1.挂载子节点和元素的属性: vnode.children的值为字符串类型时,会把它设置为…

019 | 在线电影娱乐网站系统设计含论文 | 大学生毕业设计 | 极致技术工厂

作为一个在线电影娱乐网站系统,它展示给浏览者的是各种电影信息,把这些信息能够按用户的需要友好的展示出来是很重要的,同时,能够实现对这些信息的有条不紊的管理也是不可以忽视的。对浏览者和会员的功能而言叫做前台实现&#xf…

[附源码]Node.js计算机毕业设计电子购物商城Express

项目运行 环境配置: Node.js最新版 Vscode Mysql5.7 HBuilderXNavicat11Vue。 项目技术: Express框架 Node.js Vue 等等组成,B/S模式 Vscode管理前后端分离等等。 环境需要 1.运行环境:最好是Nodejs最新版,我…

[附源码]计算机毕业设计电商小程序Springboot程序

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: Springboot mybatis MavenVue等等组成,B/S模式…

【GRU时序预测】基于卷积神经网络结合门控循环单元CNN-GRU实现时间序列预测附matlab代码

✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。 🍎个人主页:Matlab科研工作室 🍊个人信条:格物致知。 更多Matlab仿真内容点击👇 智能优化算法 …

代码随想录训练营第49天|LeetCode 121. 买卖股票的最佳时机、122.买卖股票的最佳时机II

参考 代码随想录 题目一&#xff1a;LeetCode 121. 买卖股票的最佳时机 注意这个题只买卖一次&#xff01;&#xff01; 贪心 class Solution { public:int maxProfit(vector<int>& prices) {int low INT_MAX;int result 0;for(int i 0; i < prices.size(…

Redis框架(十):大众点评项目 订单功能 Redis实现全局唯一ID、 秒杀基本环境

大众点评项目 订单功能 秒杀基本环境需求&#xff1a;订单功能 秒杀基本环境Redis实现全局唯一ID业务实现代码总览总结SpringCloud章节复习已经过去&#xff0c;新的章节Redis开始了&#xff0c;这个章节中将会回顾Redis实战项目 大众点评 主要依照以下几个原则 基础实战的Dem…

揭秘!全球2022年Salesforce不同招聘职位的平均薪资

Salesforce可以说是发展最快的企业软件公司。此外&#xff0c;还一直被评选为全球最佳工作场所之一&#xff0c;2021年赢得了Glassdoor评选的最佳工作场所&#xff0c;并且在《财富》杂志的100家最佳工作公司中排名第四。除了非常重视员工福利&#xff0c;强调工作与生活的平衡…

在WSL中配置GPU环境

首先需要明确一点&#xff0c;虽然我们通过安装WSL获得了linux开发环境&#xff0c;但是我们最终使用的GPU还是在windows当中的&#xff0c;所以还是需要在系统中安装对应的驱动。 第一步&#xff1a;在window上根据显卡型号和版本安装驱动 这里参考之前的步骤就行 第二步&a…

HPC走出全新路线:《开放架构HPC技术与生态白皮书》注解

文|智能相对论 作者|叶远风 数字经济大时代&#xff0c;创新驱动大环境&#xff0c;HPC已不再是阳春白雪&#xff0c;而受到越来越多人的关注。 HPC&#xff0c;即High Performance Computing&#xff0c;高性能计算。对普通人来说&#xff0c;没有听过HPC&#xff0c;但肯定…

使用docker-compose搭建mysql主从复制

使用docker-compose搭建mysql主从复制&#xff1a; Mysql的主从【快速】搭建编写脚本编写 master.sh 脚本编写 slave.sh 脚本编写docker-compose.yml文本测试阶段主从同步效果主从环境重启容器被删除&#xff0c;重新启动从节点关闭&#xff0c;主节点继续写入数据从节点删除&a…