删除链表的倒数第N个结点(中等)

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

示例:

示例一:
输入:head = [1,2,3,4,5], n = 2
输出:[1,2,3,5]
示例二:
输入:head = [1], n = 1
输出:[]
实例三:
输入:head = [1,2], n = 1
输出:[1]

A:思路:对于本题来讲,其本质仍为删除链表中的某个结点,而想要删除链表中的结点,则一般需要找到待删除结点的上一个结点,然后改变next指针即可。

    该题的需求是删除倒数第n个结点,那么我们的任务就分为了两步,第一步是找到待删除结点的上一个结点(为了方便删除),第二是更改next指针指向即可。很显然,该题的难点在于:如何去找到倒数第n个结点的上一个结点呢。归根结底,我们其实需要找的是倒数第 n + 1 个结点(第一步),而删除的是倒数第 n 个结点(第二步)。

    对于链表这一类的题来讲,我们最好都去创建一个虚拟哑结点去指向头结点,这么做的目的就是:插入或删除链表中的任何结点都是很方便的。我们知道,在链表中头和尾是比较特殊的,一个没有前驱,一个没有后继,尤其是操作头结点时,若有了虚拟哑结点那就相当方便和简洁了。接下来开始解题,分两步走:

    第一步:找到第 n + 1 个结点(利用快慢双指针)

    定义两个快慢指针slow和fast,起始均指向dummyNode,随后为了使得后续同时移动快慢指针时,使得二者之间的距离恒为 n + 1 ,故先让fast移动 n + 1次。

    即:

while(n != 0 && fast != null){ // while循环中移动了n次
fast = fast.next;
--n;
}
fast = fast.next; // 这里再移动一次,fast一共移动了n + 1次

     此时,fast指向了正数第 n + 2个结点,但是我们要找的是倒数第 n + 1个结点。现在哑结点和fast指针所指结点之间是一共有 n 个结点的,随后,当fast != null时,同时移动fast和slow,当fast指向null时,slow正好指向了倒数第 n + 1个结点。

     即:

while(fast != null){ //  当fast不为空时,同时移动slow和fast
fast = fast.next; // fast最终指向了null
slow = slow.next; // slow最终指向了待删除节点的上一个结点,即倒数 n + 1 个结点
}

     第二步:删除的是倒数第 n 个结点

    当找到倒数第 n + 1个结点后,删除就非常简单了,利用 slow.next = slow.next.next 即可。

    这里也要注意一点的就是,删除结点对于不用的编程语言来讲,并非是slow.next = slow.next.next 就万事大吉了。这只是在逻辑上的删除,而在物理即内存中并不一定就被删除掉了。对于Java语言来说,我们并不需要做多余的操作,垃圾回收器gc会帮我们去回收该结点并释放内存;但对于C++来讲,就需要手动的去删除和释放内存空间了,毕竟偏底层的高级语言可以较为直接的去操作内存,即是优点但也可能是个缺点,所以对于C++来说,逻辑上删除后,还需要物理上的手动删除,即最后的删除操作应为① ListNode temp = slow.next; ②slow.next = slow.next.next; ③ delete(temp);

    以下是Java代码,仅供参考:

/**
* 这里是链表结构的定义,面试中也有可能考察,需要会写出。
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummyNode = new ListNode(0, head); // 1. 定义一个哑结点,并初始指向头结点
ListNode fast = dummyNode, slow = dummyNode; // 2. 分别定义一个快指针fast和慢指针slow均初始指向哑结点 while(n != 0 && fast != null){ // 3. 在保证fast不为空指针的情况下将其向前挪动 n 次
fast = fast.next;
--n;
}
fast = fast.next; // 4. fast往后多移动一位,为了使得后面slow和fast一起移动时,slow最终可以指向待删除节点的上一个节点,也是为了删除方便
while(fast != null){ // 5. 当fast不为空时,同时移动slow和fast
fast = fast.next; // 6. fast最终指向了null
slow = slow.next; // 7. slow最终指向了待删除节点的上一个结点,即倒数 n + 1 个结点处
}
slow.next = slow.next.next; // 8. 更改slow的next指针,以删除倒数第 n 个结点
return dummyNode.next; // 9. 返回哑结点的下一个结点,即head结点
}
}

LC19. 删除链表的倒数第 N 个结点的更多相关文章

  1. 动图:删除链表的倒数第 N 个结点

    本文主要介绍一道面试中常考链表删除相关的题目,即 leetcode 19. 删除链表的倒数第 N 个结点.采用 双指针 + 动图 的方式进行剖析,供大家参考,希望对大家有所帮组. 19. 删除链表的倒 ...

  2. 2021字节跳动校招秋招算法面试真题解题报告--leetcode19 删除链表的倒数第 n 个结点,内含7种语言答案

    2021字节跳动校招秋招算法面试真题解题报告--leetcode19 删除链表的倒数第 n 个结点,内含7种语言答案 1.题目描述 给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点. ...

  3. 19. 删除链表的倒数第 N 个结点

    目录 19.删除链表的倒数第N个节点 题目 题解-暴力 题解-哈希表 题解-双指针 19.删除链表的倒数第N个节点 题目 给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点. 输入:he ...

  4. 【力扣】19. 删除链表的倒数第 N 个结点

    给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点. 进阶:你能尝试使用一趟扫描实现吗? 示例 1: 输入:head = [1,2,3,4,5], n = 2输出:[1,2,3,5]示例 ...

  5. 打败算法 —— 删除链表的倒数第n个结点

    本文参考 出自LeetCode上的题库 -- 删除链表的倒数第n个结点,官方的双指针解法没有完全符合"只遍历一遍链表"的要求,本文给出另一种双指针解法 https://leetco ...

  6. 【链表】【leetCode高频】: 19. 删除链表的倒数第 N 个结点

    1.题目描述 给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点. 2.算法分析 知识补充: . 分析: 题目要求是删除链表中倒数第N个结点.可以使用两个指针slow,fast. 重点是 ...

  7. 【算法训练营day4】LeetCode24. 两两交换链表中的结点 LeetCode19. 删除链表的倒数第N个结点 LeetCode面试题 02.07. 链表相交 LeetCode142. 环形链表II

    [算法训练营day4]LeetCode24. 两两交换链表中的结点 LeetCode19. 删除链表的倒数第N个结点 LeetCode面试题 02.07. 链表相交 LeetCode142. 环形链表 ...

  8. 四种语言刷算法之删除链表的倒数第 N 个结点

    力扣19. 删除链表的倒数第 N 个结点 1.C /**  * Definition for singly-linked list.  * struct ListNode {  *     int v ...

  9. 【LeetCode】19. Remove Nth Node From End of List 删除链表的倒数第 N 个结点

    作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 个人公众号:负雪明烛 本文关键词:链表, 删除节点,双指针,题解,leetcode, 力扣 ...

  10. LeetCode Remove Nth Node From End of List 删除链表的倒数第n个结点

    /** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode ...

随机推荐

  1. 记一次dubbo服务丢失的问题排查

    主要环境与用到的(关键)组件: Springboot2.3.2 其中,dubbo-spring-boot-starter版本为2.7.8 zookeeper3.5.9 首先是服务报错: No prov ...

  2. Java输入与输出语句详细解析

    前言 我们在前面的文章中,学习了如何创建Java文件,也学习了Java里的标识符.运算符.进制等内容.有些同学觉得还不够过瘾,给壹哥发来了好多私信,期待我能够把进度更新的再快一点.这不,新内容这就给大 ...

  3. 记一次winfrom 面板改变背景图片

    this.panel1.BackgroundImage = Image.FromFile(@"D:\TestDemo\WindowsFormsApp2\WindowsFormsApp2\黑箭 ...

  4. Cannot read properties of undefined (reading 'toUpperCase')

    无法读取 JS 中未定义的属性"toUpperCase"|鲍比哈兹 (bobbyhadz.com) 根据其中的内容找到了答案:使用了未定义的属性去使用toUpperCase()函数 ...

  5. Windows Server 远程桌面(RDP)使用公网可信机构所签发的SSL证书的方法

    Windows Server 远程桌面默认使用系统自签名证书,在任何终端进行远程桌面登录时均会提示证书告警 虽然可以通过勾选下方"不再询问我是否连接到此计算机"选项使之后登录不再提 ...

  6. put、delete、post、get四种传参方式

    PUT: this.$http.put('url', { modifyTime:this.sizeForm.modifyTime, mqttRes:this.sizeForm.mqttRes, udp ...

  7. HaProxy 安装搭建配置

    HaProxy简介 HAProxy是一个免费的负载均衡软件,可以运行于大部分主流的Linux操作系统上. HAProxy提供了L4(TCP)和L7(HTTP)两种负载均衡能力,具备丰富的功能.HAPr ...

  8. ChatGPT,我彻彻底底沦陷了!

    当谈到人工智能技术的时候,我们会经常听到GPT这个术语.它代表"Generative Pre-trained Transformer",是一种机器学习模型,采用了神经网络来模拟人类 ...

  9. 【LeetCode回溯算法#extra01】集合划分问题【火柴拼正方形、划分k个相等子集、公平发饼干】

    火柴拼正方形 https://leetcode.cn/problems/matchsticks-to-square/ 你将得到一个整数数组 matchsticks ,其中 matchsticks[i] ...

  10. 【数据结构与算法】无向图的结构与遍历 BFS&DFS

    1 表示无向图的数据类型 1.1 邻接矩阵 可以使用一个V*V的二维布尔矩阵,当定点v和定点w相连的时候,定义第v行第w列的值为true,否则为false.邻接矩阵不适合定点较多的情况,含有百万的顶点 ...