删除链表的倒数第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. luffy项目全局配置

    一:media文件夹配置 settings.dev下配置media文件夹,暴露资源 media_path=BASE_DIR.parentMEDIA_ROOT=Path(media_path).join ...

  2. .NET周报 【3月第2期 2023-03-12】

    国内文章 ASP.NET Core中如何限制响应发送速率(不是调用频率) https://www.cnblogs.com/coredx/p/17195492.html ASP.NET Core中有很多 ...

  3. VSCode使用小技巧

    VSCode写C/C++项目 我们需要先下载minGW,并需要在VS Code里面下载相应的插件, 如下: 然后,将vscode保存c++项目的文件夹用vscode打开,就会出现这样的形式: 一个标准 ...

  4. TSCTF-J 2022 WP

    Re baby_xor 加密逻辑如上,密文动态调试,然后 Shift+E 导出密文[这样避免了手动获取] # encoding=utf-8 enc=[ 0x12, 0x00, 0x00, 0x00, ...

  5. 一文带你吃透Redis

    目录 1. 基本数据结构 2. 数据持久化 3. 高可用 4. 缓存 文章字数大约1.9万字,阅读大概需要66分钟,建议收藏后慢慢阅读!!! 1. 基本数据结构 什么是Redis Redis是一个数据 ...

  6. 最大流应用(Maximum Flow Application)

    1. 二分图匹配(Bipartite Matching) 1.1 匹配(Matching) Def. Given an undirected graph \(G = (V, E)\), subset ...

  7. wsl 中 docker-compose 搭建 kafka 集群出现的外部访问错误

    在 wsl 中用 docker-compose 搭建了一台 zookeeper + 三台 broker 的 kafka 集群,使用的镜像是 bitnami/kafka,在按照镜像文档运行容器后,发现运 ...

  8. DevOps 在未来将如何演进?丨行业观察

    自2007年 DevOps 这一概念推出以来,越来越多企业开始将开发和运维团队结合在一起,以加快部署速度,提高软件开发生命周期的效率和协作.但是,诸多因素都会对 DevOps 是否成功产生影响,例如组 ...

  9. 在Kubernetes部署GitLab

    在Kubernetes部署GitLab 前置条件 已安装Helm工具已部署NFS自动创建PVC 使用HELM安装 [root@k8s-master01 ~]# helm repo add gitlab ...

  10. 在Ubuntu 18.04上安装NVIDIA

    安装NVIDIA显卡驱动风险极大,新手注意. 在Ubuntu 18.04上安装NVIDIA有三种方法: 使用标准Ubuntu仓库进行自动化安装 使用PPA仓库进行自动化安装 使用官方的NVIDIA驱动 ...