链表part02

今天是8月3日,学习了链表的第二部分。

  1. 交换链表两个节点,考察对next的操作和tmp的灵活运用。
  2. 删除链表的倒数第N个节点,双指针减少遍历次数。
  3. 链表相交,移动链表尾对齐,其实就是动长链表的指针。
  4. 环形链表,记住方法。

4. 24交换链表两个节点

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


交换节点比上一道更明显,需要更改原始列表中的节点的next。那么需要合理设置指针+更换next的顺序+及时存储tmp

  1. 注意指针指的位置:比如节点1->2->3,那么cur指向1,可以操作2和3的next。
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移动两位,准备下一轮交换}ListNode* result = dummyHead->next;delete dummyHead;return result;
}

5. 19删除链表的倒数第N个节点(双指针)

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


链表只可以从前往后挨个遍历,想要一遍解决问题常用双指针。删除倒数第n个,只需要让fast早走n步,然后fast和slow同步走,fast走到末尾时,slow->next就是要被删除的节点。

要删除某个点,slow需要指着这个点的上一个节点,才可以做到删除。

ListNode* removeNthFromEnd(ListNode* head, int n) {// 虚拟头节点 ListNode* dummyhead = new ListNode(0);dummyhead->next=head;//快慢指针ListNode* fast = dummyhead;ListNode* slow = dummyhead;//先动fast指针while(fast->next!=nullptr){//保证动fast时不出界if(n>0){n--;fast=fast->next;}   elsebreak; }//fast和slow同时动,直到fast到达最后一个节点停止while(fast->next!=nullptr){fast=fast->next;slow=slow->next;}// ListNode *tmp = slow->next;  C++释放内存的逻辑// slow->next = tmp->next;// delete tmp;slow->next=slow->next->next;return dummyhead->next;
}

6. 链表相交(移动链表尾对齐)

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


求两个链表交点节点的指针。最普通的想法,两个for嵌套,但是考虑相交的特点,相交点后面的都一样,所以:

  1. 求出两个链表的长度,并求出两个链表长度的差值,然后让两个链表末尾对齐的位置。
  2. 此时比较curA和curB是否相同,如果不相同,同时向后移动curA和curB,如果遇到curA == curB,则找到交点。
  3. 否则循环退出返回空指针。
  1. 交点不是数值相等,而是指针相等。
  2. 链表尾对齐,其实就是curA移动到中间,剩下的A链表和B一样长。
 ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {ListNode* curA = headA;ListNode* curB = headB;int lenA = 0, lenB = 0;while (curA != NULL) { // 求链表A的长度lenA++;curA = curA->next;}while (curB != NULL) { // 求链表B的长度lenB++;curB = curB->next;}curA = headA;curB = headB;// 让curA为最长链表的头,lenA为其长度if (lenB > lenA) {swap (lenA, lenB);swap (curA, curB);}// 求长度差int gap = lenA - lenB;// 让curA和curB在同一起点上(末尾位置对齐)while (gap--) {curA = curA->next;}// 遍历curA 和 curB,遇到相同则直接返回while (curA != NULL) {if (curA == curB) {return curA;}curA = curA->next;curB = curB->next;}return NULL;}

7. 142环形链表

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


a. 如何判定是否有环?

快慢指针法,定义 fast 和 slow 指针,从头结点出发,fast指针每次移动两个节点,slow指针每次移动一个节点,如果 fast 和 slow指针在途中相遇 ,说明这个链表有环。

  • fast指针一定先进入环中,如果fast指针和slow指针相遇的话,一定是在环中相遇。
  • 相对于slow来说,fast是一个节点一个节点的靠近slow的,所以fast一定可以和slow重合。

b. 如何判断环的起始点?

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

因为fast指针是一步走两个节点,slow指针一步走一个节点, 所以 fast指针走过的节点数 = slow指针走过的节点数 * 2:

(x + y) * 2 = x + y + n (y + z)

两边消掉一个(x+y): x + y = n (y + z)

因为要找环形的入口,那么要求的是x,因为x表示 头结点到 环形入口节点的的距离。

所以要求x ,将x单独放在左面:x = n (y + z) - y = (n - 1) A + z

因此,发现从相遇点到入环点的距离z加上 n−1 圈的环长,恰好等于从链表头部到入环点的距离x。

因此,当发现 slow 与 fast 相遇时,再额外使用一个指针 ptr。起始,它指向链表头部;随后,它和 slow 每次向后移动一个位置。最终,它们会在入环点相遇。

ListNode *detectCycle(ListNode *head) {ListNode* fast = head;ListNode* slow = head;while(fast != NULL && fast->next != NULL) {slow = slow->next;fast = fast->next->next;// 快慢指针相遇,此时从head 和 相遇点,同时查找直至相遇if (slow == fast) {ListNode* index1 = fast;ListNode* index2 = head;while (index1 != index2) {index1 = index1->next;index2 = index2->next;}return index2; // 返回环的入口}}return NULL;
}

今日古诗

西江月·日日深杯酒满
朱敦儒〔宋代〕

日日深杯酒满,朝朝小圃花开。自歌自舞自开怀,无拘无束无碍。
青史几番春梦,黄泉多少奇才。不须计较与安排,领取而今现在。

上片起首写出词人终日醉饮花前的生活。深杯酒满见得饮兴之酣畅,小圃花开点出居处之雅致。无一字及人,而人的精神风貌已隐然可见。后二句则直陈快乐自由的情态;
下片文情陡变,两个对句表达了词人对世事人生的认识,末句是对上片所描述闲逸自得生活之底蕴的概括和揭示。全词用语浅自而意味悠远,清新淡雅,韵味天成,语意俱佳,流露出一种闲旷的情调

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

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

相关文章

Qt-pyqt6与QTDesginers的相互使用技巧

1. 先在QT Designers Tools 设计器中画好框架,再保存为.ui文件导出 2. 再pycharm中创建一个main.py文件用来加载和使用这个.ui文件,通用的代码如下: main.py from PyQt6.QtGui import QIntValidator, QIcon from PyQt6.QtWidgets import QApplication, QLabel, QListWidgetI…

Go中使用Zap日志库与Lumberjack日志切割

Go中使用Zap日志库与Lumberjack日志切割Go中使用Zap日志库与Lumberjack日志切割 原创 何泽丰 ProgrammerHe2024年06月11日 20:15 广东 听全文Go中使用Zap日志库与Lumberjack日志切割 概述 在项目中使用日志记录有助于快速定位和修复问题,能帮助我们监控系统健康状态及时发现问…

[UnrealCircle]腾讯 罗谦 | UnLua-UE4下的Lua脚本插件

传送门:[UnrealCircle]腾讯 罗谦 | UnLua-UE4下的Lua脚本插件_哔哩哔哩_bilibili参考PPT:UnrealCircle921北京PPT_免费高速下载|百度网盘-分享无限制一. UnLua 基础 1.1 概念UnLua 是一个脚本插件 UnLua 不是蓝图的替代,而是一种补充没有 Asset 预览 不支持 nativization 无…

Zigzag :nested loop 的教科书

Zigzag 在 PE array-memory hierarchy level 上对 nested-loop based 算子数据部署设计策略进行详细分析。文章作者来自鲁汶 MICAS [1]实验室。 软硬件建模 软件上只涉及 MAC-based 的网络算子(Linear、Convolutional),沿用 time-loop [2] 方法使用 nested-loop 建模,从 op…

6、Qt-pyqt6常用基本控件 - 选择列表类控件

选择列表类控件主要以列表形式为童虎提供选择的项目,用户可以从中选择项 此选项在QTDesigner的:Input Widgets下ComboBox FontComBoBox ListWidget🎣 1.ComboBox 下拉框 常用的方法:方法 说明addItem() 添加一个下拉表选项addItems() 从列表中给添加下拉选项currentText()…

蒙特卡洛模拟(4)————书店买书问题(0-1规划)

目录一、问题提出二、模型建立1.符号建立2.规定约束3.获得目标函数三、代码求解1.预备知识(1)unique函数(2)randi函数2.变量设置与初始化3.输入循环进行模拟四、模型拓展 一、问题提出二、模型建立 1.符号建立 在图表上,我们可以看见有六家商店和五本书,在代码中我们往往…

KubeSphere 社区双周报| 2024.07.19-08.01

KubeSphere 社区双周报主要整理展示新增的贡献者名单和证书、新增的讲师证书以及两周内提交过 commit 的贡献者,并对近期重要的 PR 进行解析,同时还包含了线上/线下活动和布道推广等一系列社区动态。 本次双周报涵盖时间为:2024.07.19-08.01。 贡献者名单新晋 KubeSphere co…

内核简介

Linux内核基础 楔子 这部分的内容首先要回忆一下计算机的基础知识,基本的计算机结构包括CPU(算数逻辑单元ALU、控制单元CU)、存储器、输入和输出。CPU和其它设备是通过总线连接的。CPU执行的基础被称为指令集,CPU执行存储器存取指令时:CPU发出存取信号,然后就从存储器存取…

logback下日志输出前处理操作——以日志脱敏为例

使用lockback 目前Java Spring服务在打印日志时一般使用slf4j和logback这种组合,其基本原理图如下具体的:大多数会先定义一个loackback-dev.xml文件,而后使用<appender>标签定义输出格式 <appender name="file" class="ch.qos.logback.core.rolling…

边分治维护强连通分量(CF1989F,P5163)

这里的边分治和树上的点分治边分治不一样,是维护强连通分量用的,每条边有一个出现时间,通过将每条边按连通关系分流重新排列,从而维护每个时间点整张图的连通性。具体的,这个算法是维护这样的一类问题: n 个点,m 条边按时间顺序依次加入,每加入一条边,你需要回答一些问…