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

相关推荐
AomanHao1 小时前
【阅读笔记】Weighted Guided Image Filtering(WGIF)权重引导滤波
图像处理·人工智能·笔记·计算机视觉·滤波·引导滤波
weixin_440730502 小时前
字符编码笔记-utf-8 、unicode、gbk,ascii编码格式
开发语言·笔记
andyweike10 小时前
php笔记
开发语言·笔记·php
xian_wwq11 小时前
【学习笔记】等保合规安全基线核查实战
笔记·学习
M78佐菲12 小时前
ARM学习笔记(11)
linux·arm开发·笔记·嵌入式硬件·学习
M78佐菲12 小时前
ARM学习笔记(10)
linux·arm开发·笔记·嵌入式硬件·学习
李游Leo13 小时前
HarmonyOS 7 + ArkUI + RelationalStore 学习笔记:本地数据分层存储与状态持久化架构实践【鸿蒙心迹】
笔记·学习·架构·harmonyos
Cccp.12313 小时前
【leetcode】(七)前缀树和贪心算法
数据结构·leetcode·贪心算法
我命由我1234513 小时前
经纪人的职业定义
经验分享·笔记·学习·职场和发展·求职招聘·职场发展·学习方法
摇滚侠14 小时前
《On Java 中文版 基础卷》阅读笔记 对象无处不在 03
java·笔记·python