刷题笔记:力扣第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步后再多走一步。

相关推荐
Micahㅤ1 小时前
【EMC测试报告笔记】报 告里写 CE、骚扰功率、EN55022-MainTermB,到底在测什么?
笔记·emc·电磁兼容性
菜鸟的升级路2 小时前
C语言栈刷题:LeetCode 20 有效的括号完整解题笔记
c语言·笔记·leetcode
晓梦林2 小时前
[Dest0g3 520迎新赛]EasyPHP-学习笔记
android·笔记·学习
Lsir10110_2 小时前
【力扣hot100】矩阵题通关复盘
算法·leetcode·矩阵
退休倒计时2 小时前
【每日一题】LeetCode 207. 课程表 TypeScript
算法·leetcode·typescript
小黄蚁3 小时前
LVGL学习笔记(一)
笔记·学习
玖玥拾3 小时前
LeetCode 80 删除有序数组中的重复项 II
算法·leetcode
青山木3 小时前
Hot 100 --- 电话号码的字母组合
java·数据结构·算法·leetcode·逻辑回归
懿路向前3 小时前
【HarmonyOS学习笔记】2026-07-26 | @Trace 序列化 __ob_ 前缀陷阱与消息持久化
笔记·学习