代码随想录刷题-链表-删除链表的倒数第N个节点
创始人
2025-05-29 05:18:32
0

删除链表的倒数第N个节点

本节对应代码随想录中:代码随想录,讲解视频:链表遍历学清楚! | LeetCode:19.删除链表倒数第N个节点_哔哩哔哩_bilibili

习题

题目链接:19. 删除链表的倒数第 N 个结点 - 力扣(LeetCode)

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

  • 输入:head = [1,2,3,4,5], n = 2;输出:[1,2,3,5]
  • 输入:head = [1], n = 1;输出:[]
  • 输入:head = [1,2], n = 1;输出:[1]

直观解法

这道题目还挺简单的,题意也很明确。需要注意的是最好使用虚拟头结点,否则示例2这种就需要单独处理会麻烦一点。比较容易想到的就是既然要删倒数第 n 个节点,那我们首先遍历以下链表看看总共有多少个节点,然后再根据总节点数量 size 和 n 的大小遍历到待删节点的前一个节点执行删除操作即可。

这里需要注意的就是遍历的边界条件是到了待删节点的前一个节点开始执行删除操作。当遍历到待删节点本身的时候是无法进行删除的,因为我们无法获得待删节点的前一个节点是什么。

class Solution {public:ListNode* removeNthFromEnd(ListNode* head, int n) {ListNode* dummyHead = new ListNode(0);dummyHead->next = head;ListNode* tmp = head;int size = 0;   // 记录链表长度// 计算链表长度while (tmp != nullptr) {tmp = tmp->next;size++;}tmp = dummyHead;// 找到待删除节点的前一个节点for (int i = 0; i < size - n; i++) {tmp = tmp->next;}ListNode* delNode = tmp->next;tmp->next = tmp->next->next;delete delNode;return dummyHead->next;}
};

可以优化的点:

  • 今天看官方题解突然发现 ListNode* dummyHead = new ListNode(0);dummyHead->next = head; 这两句其实可以用 ListNode* dummyHead = new ListNode(0, head); 这一句话来实现。因为 ListNode 的构造函数中有这样一句 ListNode(int x, ListNode *next) : val(x), next(next) {} 可以直接指定节点的 next,不过写成两句更加直观一点。

双指针

LeetCode 上题目描述中进阶中说“你能尝试使用一趟扫描实现吗?”。一开始没想出来,看了题目的提示:Maintain two pointers and update one with a delay of n steps.才明白。

例如0 1 2 3 4 5,我们可以用一个指针 cur 来遍历,用另一个指针 pre 慢 cur 指针 n+1 步遍历。比如 n=2时,当 cur=3时,pre=0(虚拟头结点),然后两个指针一起移动,当 cur 遍历到5后面的 nullptr 时,pre 刚好遍历到待删节点4的前一个节点3的位置。

如果是慢 n 步遍历,那么 pre 会遍历到待删节点4的位置,此时是无法执行删除节点4的操作的,因此是慢 n+1步。

class Solution {public:ListNode* removeNthFromEnd(ListNode* head, int n) {ListNode* dummyNode = new ListNode(0);dummyNode->next = head;ListNode* cur = dummyNode;ListNode* pre = dummyNode;// cur先向前移动n+1步for (int i = 0; i < n + 1; i++) {cur = cur->next;}// 然后cur和pre一起向前移动while (cur != nullptr) {cur = cur->next;pre = pre->next;}ListNode* delNode = pre->next;pre->next = pre->next->next;delete delNode;return dummyNode->next;}
};

但是写完之后又有点疑惑,这还算是一趟扫描吗,因为其中有 for 循环和 while 循环。仔细琢磨后发现确实算是一趟扫描。

直观解法的解法中,在第一趟扫描中,需要计算链表的长度,以便确定需要删除节点的前一个节点。而在第二趟扫描中,才真正开始删除节点。因此,这个解法需要进行两趟扫描。而双指针解法使用了两个指针来记录待删除节点的前一个节点,而不需要事先计算链表的长度。

举个极端点的例子,在1000个节点中,我想删除倒数第1个节点即节点1000,在第一个解法中,需要先遍历1000个节点得知链表长度为1000,然后再遍历一趟到节点999的位置执行删除操作。而在第二个解法中,只需要 cur 指针先向前走2步,然后 pre 指针和 cur 指针再开始一起走,最后 cur 指针走到节点1000的下一个即 nullptr 时,pre 刚好走到节点999的位置。在这个例子中,解法一走了1001+999=1999步,而解法二只走了1001+2=1003步!

为什么是1001而不是1000?因为从1000走到下一步 nullptr 还需要一步

如果你还是有点不太理解,看看下面的代码,它没有使用 for 循环而是使用了 size 进行计数,其实和上面的解法是一个意思。

class Solution {public:ListNode* removeNthFromEnd(ListNode* head, int n) {ListNode* dummyHead = new ListNode(0);dummyHead->next = head;ListNode* cur = dummyHead;ListNode* pre = dummyHead;int size = 0;while (cur != nullptr) {// size > n说明慢指针可以开始移动了if (size > n)// 循环结束后pre指向待删除节点的前一个节点pre = pre->next;elsesize++;cur = cur->next;}ListNode* delNode = pre->next;pre->next = pre->next->next;delete delNode;return dummyHead->next;}
};

相关内容

热门资讯

小学生元宵节日记优秀 小学生元宵节日记优秀范文小学生元宵节日记优秀范文1  今天是正月十五,也就是元宵节,中国的传统节日。...
三国演义之关羽读书笔记 三国演义之关羽读书笔记600字  武艺超群,谋略高深,骄傲自大?“武圣关公”在武艺上是一人之下万人之...
缓存穿透,缓存雪崩,缓存击穿 注:该文章基于黑马程序员中《黑马点评》软件的学习 视频链接 涉及视频 p40p42p4...
插件化架构设计(1):插件化架... 前面是概念内容,在实现的时候,google 搜的资料进行汇总所做的笔记&...
JavaWeb开发(四)4.2... 一、SpringMVC 请求与响应 1、@RequestMapping 注解 @Re...
开学日记500字 开学日记500字  开学,汉语解释有开设学校、启作学者、学期开始三个释义。以下是小编收集的开学日记相...
朝花夕拾读书笔记摘抄好词好句 朝花夕拾读书笔记摘抄好词好句  一、朝花夕拾的主要内容  《朝花夕拾》里作者鲁迅用夹叙夹议的方法,以...
net.coobird.thu... 1.简单介绍 net.coobird.thumbnailator.Thumbnails 是一个用于创...
《红楼梦》读书笔记 《红楼梦》读书笔记600字《红楼梦》读书笔记600字娴静似娇花照水,行动如弱柳扶风,心较比干多一窍,...
增广贤文读书笔记 增广贤文读书笔记(精选30篇)  读完一本名著以后,想必你有不少可以分享的东西,何不写一篇读书笔记记...
[解决]Splunk KV S... 1: 背景: 今天客户反映数据搜索的时候,不是很稳定,想确定一下 ,这个是什么原因造成的,我去系统里...
爱的教育作文 爱的教育作文爱的教育看到这个书名,我不禁开始思考一个问题:在这个缤纷多彩的世界里,爱究竟是什么含义?...
梁衡《把栏杆拍遍》读书笔记 梁衡《把栏杆拍遍》读书笔记梁衡《把栏杆拍遍》读书笔记这是一篇写得很美的散文,有以下特点:一、联想丰富...
【每日一题Day150】LC1... 分割两个字符串得到回文串【LC1616】 给你两个字符串 a 和 b ,它们长度相同...
一年级春游日记 一年级春游日记一年级春游日记1  今天是春游,我作天就去买许多零食和矿泉水,打算在春游的时候干掉,我...
课外读书笔记摘抄 课外读书笔记摘抄(精选12篇)  导语:舍弃就是这样,它也许出于无奈,可在无奈之后是另一份希望,它也...
蚂蚁观察日记 【热门】蚂蚁观察日记4篇蚂蚁观察日记 篇1  我家有一个后院,我经常到后院去观察那些鹭绿上得小精灵—...
ImageView(图像视图) 本节介绍的UI基础控件是:ImageView(图像视图),就是用来显示图像的一个View或者说控件!...
关于接口测试——自动化框架的设... 一、自动化测试框架 在大部分测试人员眼中只要沾上“框架”,就感觉非常神秘,...
【2023.3.8】数据结构复... 【2023.3.8】数据结构复习笔记 文章目录【2023.3.8】数据结构复习笔记序言一、绪论二、线...