刷题笔记:力扣第19题-删除链表的倒数第N个结点

1.初步思路为两趟扫描,第一趟获取链表节点数cnt,第二趟根据cnt和n找到需要删除的节点,执行删除操作。写出的完整代码如下:

cpp 复制代码
 1. /**
 2.  * Definition for singly-linked list.
 3.  * struct ListNode {
 4.  *     int val;
 5.  *     struct ListNode *next;
 6.  * };
 7.  */
 8. struct ListNode* removeNthFromEnd(struct ListNode* head, int n) {
 9.     // 创建虚拟头节点,统一处理删除头节点的边界情况
10.     struct ListNode* dummyHead = (struct ListNode*)malloc(sizeof(struct ListNode));
11.     // 虚拟头节点连接原链表
12.     dummyHead->next = head;
13.     // cur遍历指针,先用来统计链表总节点数量
14.     struct ListNode* cur = dummyHead->next;
15.     // cnt记录链表有效节点总数
16.     int cnt = 0;
17.  
18.     // 第一次遍历,统计链表节点个数
19.     while (cur != NULL){
20.         cur = cur->next;
21.         cnt++;
22.     }
23.  
24.     // 指针重置回虚拟头,准备找到待删除节点的前驱
25.     cur = dummyHead;
26.     // 循环移动 cnt-n 次,定位到倒数第n个节点的前一个节点
27.     for (int i = 0; i < cnt - n; i++){
28.         cur = cur->next;
29.     }
30.  
31.     // 跳过待删除节点,直接连接下下个节点
32.     cur->next = cur->next->next;
33.     // 返回去掉目标节点后的链表头部
34.     return dummyHead->next;
35. }

这其中涉及的知识点:

(1)尽量使用虚拟头结点。

(2)查找的时候只关心链表的真实值,cur指向dummyHead->next。

(3)删除的时候需要找到需要删除节点的前一个节点,cur指向dummyHead。

2.进阶思路限制了只能使用一趟扫描,得知本题可以使用快慢指针,写出的完整代码如下:

cpp 复制代码
 1. /**
 2.  * Definition for singly-linked list.
 3.  * struct ListNode {
 4.  *     int val;
 5.  *     struct ListNode *next;
 6.  * };
 7.  */
 8. struct ListNode* removeNthFromEnd(struct ListNode* head, int n) {
 9.     // 创建虚拟头节点,处理需要删除原头节点的边界场景
10.     struct ListNode* dummyHead = (struct ListNode*)malloc(sizeof(struct ListNode));
11.     dummyHead->next = head;
12.     // cur作为快指针,先向前走n步拉开间距
13.     struct ListNode* cur = dummyHead;
14.     for (int i = 0; i < n; i++){
15.         cur = cur->next;
16.     }
17.     // 快指针再多走一步,保证慢指针最终停在待删节点前驱
18.     cur = cur->next;
19.  
20.     // del作为慢指针,初始指向虚拟头
21.     struct ListNode* del = dummyHead;
22.     // 快慢指针同步后移,直到快指针走到链表末尾NULL
23.     while (cur != NULL){
24.         cur = cur->next;
25.         del = del->next;
26.     }
27.  
28.     // 慢指针跳过倒数第n个节点,完成删除
29.     del->next = del->next->next;
30.  
31.     // 返回修改后的链表头节点
32.     return dummyHead->next;
33. }

因为n一定小于链表节点数,所以一定不会越界,于是可以让快指针先走n步,然后慢指针再出发,这样可以保证当快指针走到末尾时与慢指针的距离正好为n。同时又因为删除节点需要找到需要删除节点的上一个节点,所以需要让快指针走完n步后再多走一步。

相关推荐
无聊的菜鸟33 分钟前
TMS320F2806X学习笔记(零)—— C2000、CCS、新建工程
笔记·mcu·c2000·f2806x
ljt27249606612 小时前
Compose笔记(八十三)--onVisibilityChanged
笔记
Scabbards_3 小时前
面试Leetcode - Heap 堆
java·leetcode·面试
Fa_Mian_Tuan5 小时前
图论基础|邻接矩阵超详细讲解(含无向/有向/带权图+完整可运行C语言代码)
c语言·数据结构·笔记·算法·图论
ValhallaCoder6 小时前
Leetcode-hot100(2026.08.17)
python·算法·leetcode
zhangrelay6 小时前
ROS 2 Lyrical 第9章 计算机视觉与摄像头应用
linux·笔记·学习·ubuntu·机器人·ros2
FakeOccupational7 小时前
【电路笔记 STM32】stm32f103 实现HAL_UART_Transmit_DMA + 普通模式/连续模式的 UART DMA 收发
笔记·stm32·嵌入式硬件
北京海得康8 小时前
DMD基因治疗deramiocel遭FDA质疑,Ultragenyx DTX401即将获批
笔记
zjnlswd8 小时前
C#学习笔记2 刘铁锰
笔记·学习
Mr_liu_6668 小时前
Claude非专业入门实战笔记(4):Claude运行方式简单解析——从RAG到代理循环
笔记·ai编程·claude