当前位置: 首页 > news >正文

算法入门打卡Day4___交换链表节点、删除倒数N个节点、链表相交、环形链表

算法入门打卡Day4

今日收获

  1. 交换链表中的节点
  2. 快慢指针法删除链表倒数第N个节点
  3. 链表相交问题
  4. 环形链表问题
  5. 了解到了 && 运算符的特性

学习时长:3.5h

正文

两两交换链表中的节点

LeetCode24

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

img

解答方法:画图找出增删方式,搞清链表的顺序,别搞错cur的位置就行。

class Solution {
public:ListNode* dummyHead = new ListNode;ListNode* swapPairs(ListNode* head) {dummyHead->next = head;ListNode* cur = dummyHead;ListNode* tmp1;ListNode* tmp2;while (cur->next != nullptr && cur->next->next != nullptr) {tmp2 = cur->next->next->next;tmp1 = cur->next->next;cur->next->next = tmp2;tmp1->next = cur->next;cur->next = tmp1;cur = cur->next->next;}return dummyHead->next;}
};

注意事项

  • 每次为链表创建一个新节点时(比如虚拟头节点),一定要 new 一个新的堆区空间,因为这和 temp 临时指针不同,指针只是临时保存,而新节点是完全独立的有自己的值的。
  • 如果不需要虚拟头节点了也请记得释放内存空间,把 dummyHead delete 掉。

删除链表的倒数第N个结点(快慢指针)

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

img

这里我们使用快慢指针法

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode() : val(0), next(nullptr) {}*     ListNode(int x) : val(x), next(nullptr) {}*     ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/
class Solution {
public:ListNode* dummyHead = new ListNode;ListNode* removeNthFromEnd(ListNode* head, int n) {dummyHead->next = head;ListNode* slow = dummyHead;ListNode* fast = dummyHead;while (n + 1) {fast = fast->next;n--;}while (fast != nullptr) {slow = slow->next;fast = fast->next;}ListNode* tmp = slow->next;slow->next = tmp->next;delete tmp;return dummyHead->next;}
};

总体还是比较简单的:

  1. 快指针先移动 n 次,然后两个指针一起移动到快指针 fast 变空,这样慢指针 slow 会停留在需要被删除的元素上。
  2. 但是一般来说我们删除链表节点时停留在目标前一个节点来操作比较简单,所以这里我们让 fast 指针先移动 n+1 次就可以了。
  3. 记得释放被删除节点的内存空间防止内存泄漏。

链表相交

LeetCode面试题02.07

给你两个单链表的头节点 headAheadB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null

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

img

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

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

class Solution {
public:ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {ListNode* curA = headA;ListNode* curB = headB;int sizeA = 0, sizeB = 0;while (curA != nullptr) {curA = curA->next;sizeA++;}while (curB != nullptr) {curB = curB->next;sizeB++;}curA = headA;curB = headB;if (sizeA <= sizeB) {int c = sizeB - sizeA;while (c--) {curB = curB->next;}}if (sizeA > sizeB) {int c = sizeA - sizeB;while (c--) {curA = curA->next;}}while (curA != nullptr) {if (curA == curB) {return curA;}curA = curA->next;curB = curB->next;}return NULL;}
};
  1. 遍历两次求两链表长度差
  2. 对齐两个 cur 指针
  3. 一起向后遍历,遇到相同的指针返回值,没遇到返回 NULL

环形链表

LeetCode142

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

环形列表示例图:

img

思路:

假设从头结点到环形入口节点 的节点数为x。 环形入口节点到 fast指针与slow指针相遇节点 节点数为y。 从相遇节点 再到环形入口节点节点数为 z。 如图所示:
785e44bccd493851502f353f3c22a3db.png

那么相遇时:

slow指针走过的节点数为: x + y

fast指针走过的节点数:x + y + n (y + z)

n为fast指针在环内走了n圈才遇到slow指针, (y+z)为 一圈内节点的个数A。

fast指针走过的节点数 = slow指针走过的节点数 * 2:(x + y) * 2 = x + y + n (y + z)

因为要找环形的入口,那么要求的是x,因为x表示 头结点到 环形入口节点的的距离。所以要求x ,将x单独放在左面:x = n (y + z) - y

再从n(y+z)中提出一个 (y+z)来,整理公式之后为如下公式:x = (n - 1) (y + z) + z

这是为了得到一个正数方便我们后面遍历,注意这里n一定是大于等于1的,因为 fast指针至少要多走一圈才能相遇slow指针。

slow指针与fast指针相遇时,slow指针肯定是没有走完一圈的,因为fast指针的速度是slow的两倍,slow走一圈fast已经走两圈了。

这就意味着,从头结点出发一个指针,从相遇节点 也出发一个指针,这两个指针每次只走一个节点, 那么当这两个指针相遇的时候就是 环形入口的节点

也就是在相遇节点处,定义一个指针index1,在头结点处定一个指针index2。

让index1和index2同时移动,每次移动一个节点, 那么他们相遇的地方就是 环形入口的节点。

class Solution {
public:ListNode *detectCycle(ListNode *head) {ListNode* fast = head;ListNode* slow = head;while (fast != nullptr && fast->next != nullptr) {fast = fast->next->next;slow = slow->next;if (slow == fast) {ListNode* index1 = head;ListNode* index2 = slow;while (index1 != index2) {index1 = index1->next;index2 = index2->next;}return index1;}}return NULL;}
};
  • 这里有一个隐蔽的知识点,在以下语句中: fast != nullptr && fast->next != nullptr ,哪怕 fast 是空指针,也不需要考虑调用 fast->next 会不会变成非法访问,因为运算符 && 是从左到右进行的,一旦左边的条件不能满足,就不会对右边的条件进行判断了,于是在类似的场景下注意不要写反!!
http://www.jsqmd.com/news/329966/

相关文章:

  • 2026青少年数学网校实测|分龄选对不踩坑,学霸私藏清单曝光
  • 人民大学团队破解AI智能体“健忘症“
  • Flutter艺术探索-Flutter跨平台适配:Android/iOS/Web差异化处理
  • stm32毕业论文(毕设)必过选题思路
  • 研究团队发明了一套AI评审系统,让深度研究报告评测变得精准!
  • JAVA数据结构 DAY2-包装类和泛型
  • 毕业那年经济增速,决定你未来十年工资?
  • 阿里巴巴云团队用448K样本做出超越32倍参数模型的推理小天才
  • 深度测评9个降AI率平台,千笔助你高效降AIGC
  • 股市盈利三支柱:深耕、规则、仓位::股市的最大敌人,不是“市场”,而是“自己的认知盲区、对规则的忽视、对风险的漠视”
  • 北大联合阿里达摩院:让AI代码生成告别“只会跑不会快“的困境
  • ACPI!ACPIRootIrpStartDevice函数在ACPI!ACPIInitStartACPI函数后设置_SB的设备状态为Started
  • 2026青少年英语网校靠谱排名|实测4家!提分/启蒙/口语全覆盖
  • 实测30家|给宝妈的小学生数学网校参考,省心不踩坑
  • 2026年4-8岁儿童AI数学课程解析|科学测评+精准选课指南
  • 完整教程:PySide6 + QML - 多线程02 - QThread 生命周期与安全退出
  • 小学启蒙AI数学课怎么选?实测8大热门课,避坑指南+适配攻略
  • ue 购买 fbx 资产踩坑实录
  • 【课程设计/毕业设计】基于spring boot的汽车4s店管理系统基于SpringBoot的汽车服务管理系统【附源码、数据库、万字文档】
  • 2026线上数学课程排行榜TOP3揭晓!精准提分+思维培养,家长选课不踩坑
  • 2026青少年语文课程十大权威排行|优质机构与小程序网课双榜,家长避坑指南速藏
  • 计算机Java毕设实战-基于SpringBoot的汽车服务管理系统基于springboot车辆综合服务平台【完整源码+LW+部署说明+演示视频,全bao一条龙等】
  • 2026中学语文课程靠谱排名|家长选课不迷茫,精准适配各学段
  • 美发店连锁开题报告
  • 2026成人数学培训机构盘点:避开3大雷区,精准匹配职场需求!
  • 实测5款热门儿童AI语文课程!2026年家长选课不踩坑,附精准推荐
  • 农产品运输服务平台开题
  • 2026国内数学课程机构全解析:覆盖少儿/初高中/考研,选对不踩坑!
  • [技术攻坚] 电子产品“结构爆炸图”汉化太难修?浅析基于 AI 的“线条重建”技术,一键还原工业级质感
  • 实测才敢推!千笔写作工具,继续教育论文写作天花板