【算法题解】13. 删除链表的倒数第 N 个结点

news2024/9/25 13:16:19

文章目录

    • 题目
    • 解法一:计算链表长度
      • Java 代码实现
      • Go 代码实现
      • 复杂度分析
    • 解法二:双指针
      • Java 代码实现
      • Go 代码实现
      • 复杂度分析

这是一道 中等难度 的题。
题目来自:https://leetcode.cn/problems/remove-nth-node-from-end-of-list/description/

题目

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

示例 1
删除链表的倒数第 N 个结点

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

示例 2:

输入:head = [1], n = 1
输出:[]

示例 3:

输入:head = [1,2], n = 1
输出:[1]

提示:
链表中结点的数目为 s z sz sz

  1. 1 < = s z < = 30 1 <= sz <= 30 1<=sz<=30
  2. 0 < = N o d e . v a l < = 100 0 <= Node.val <= 100 0<=Node.val<=100
  3. 1 < = n < = s z 1 <= n <= sz 1<=n<=sz

进阶: 你能尝试使用一趟扫描实现吗?

解法一:计算链表长度

想要删除链表中的一个节点,最简单的做法就是找到这个节点的前一个节点,然后将前一个节点的next指针指向需删除节点的下一个节点。如删除 节点4,即将 节点3 的下一个节点直接指向 节点5
 删除链表的倒数第 N 个结点

题目要求删除的是倒数第n个节点,由于单链表只能从头开始往后找,所以我们需要知道需删除节点的位置从前开始数是应该是第几个。

可以先从头到尾循环一遍计算出总节点数total,那么被删除节点的位置deleteIndex应该是total + 1 - n,被删节点的前一个位置是total - n

然后从头开始循环第二遍,直接找到total - n这个位置的节点并记为pre,然后删除pre的下一个节点。

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 protect = new ListNode(0);
        protect.next = head;

        int total = 0;
        while(head != null){
            total++;
            head = head.next;
        }

        int deleteIndex = total + 1 - n;
        
        ListNode pre = protect;
        for(int i = 1; i < deleteIndex; i++){
            pre = pre.next;
        }
        pre.next = pre.next.next;
       
        return protect.next;
    }
}

Go 代码实现

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 * Val int
 * Next *ListNode
 * }
 */
func removeNthFromEnd(head *ListNode, n int) *ListNode {

    // 保护节点
    protect := &ListNode{0, head}

    // 计算链表长度
    total := 0
    for head != nil {
        total++
        head = head.Next
    }

    // 被删除节点位置
    deleteIndex := total + 1 - n

    // 找到删除节点的前一个
    pre := protect
    for i := 1; i < deleteIndex; i++ {
        pre = pre.Next
    }

    pre.Next = pre.Next.Next

    return protect.Next

}

复杂度分析

时间复杂度 O ( N ) O(N) O(N), 需要循环两遍节点,第一遍是total次,第二遍是total - n次,总的来说是线性的时间复杂度, N 位链表总节点数。
空间复杂度 O ( 1 ) O(1) O(1), 常数级空间复杂度。

解法二:双指针

解法一总共扫描了2次,题目进阶要求扫描1次如何解题?

要删除倒数第n个节点,我们需要找到倒数第n + 1个节点。在扫描一次的前提下, 我们可以使用双指针来解题:

  1. 先定义2个指针firstsecond并让它们都指向保护节点。
  2. second指针单独向后移动n + 1 个节点。
  3. firstsecond之间相差n + 1个节点时,first指针跟随second指针一起向后移动。
  4. second指针指向null的时候,这个时候first指针刚好指向删除节点的前一个节点。
  5. 删除指定节点。
    删除链表的倒数第 N 个结点

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 protect = new ListNode(0);
        protect.next = head;

        ListNode first = protect, second = protect;
        for(int i = 1; i <= n + 1; i++){
            second = second.next;
        }

        while(second != null){
            second = second.next;
            first = first.next;
        }
        first.next = first.next.next;

        return protect.next;
    }
}

Go 代码实现

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 * Val int
 * Next *ListNode
 * }
 */
func removeNthFromEnd(head *ListNode, n int) *ListNode {

    protect := &ListNode{0, head}

    first, second := protect, protect
    for i := 1; i <= n + 1; i++ {
        second = second.Next
    }

    for second != nil {
        second = second.Next
        first = first.Next
    }

    first.Next = first.Next.Next

    return protect.Next
}

复杂度分析

时间复杂度 O ( N ) O(N) O(N), 两个循环加起来second指针刚好从头走到尾,时间复杂度为链表长度。
空间复杂度 O ( 1 ) O(1) O(1), 常数级空间复杂度。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/187394.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

numpy快速交换行列

import numpy as np “”" 快速加换两行两列 “”" #交换两列第一列跟第三列 v1np.arange(100) v2v1.reshape((20,5)) v3v2[:,[0,3,2,1,4]] print(v3) “”" 快速交换两列 第一列跟第三列 “”" print() mask list(range(5))#生成一个0到4的列表 #快速…

[iHooya]2023年1月30日作业解析

温度统计 现有一段时间的温度数据&#xff0c;请统计指定温度出现的次数。 输入 第一行一个整数n,表示温度数据的个数。&#xff08;0 < n ≤ 200&#xff09; 第二行n个整数&#xff0c;以空格分隔&#xff0c;每个整数表示一个温度&#xff0c;温度的范围大于等于0&#…

OpenCV实战(9)——基于反向投影直方图检测图像内容

OpenCV实战&#xff08;9&#xff09;——基于反向投影直方图检测图像内容0. 前言1 反向投影直方图2. 反向投影颜色直方图3. 完整代码小结系列链接0. 前言 直方图是图像内容的一个重要特征。如果查看显示特定纹理或特定对象的图像区域&#xff0c;则该区域的直方图可以看作是一…

计算机网络之TCP全连接队列与半连接队列

什么是全、半连接队列 服务端接收syn请求后&#xff0c;内核会把该连接放入到半连接队列&#xff0c;服务端对synack返回ack后&#xff0c;会把连接从半连接队列移除&#xff0c;创建新的全连接&#xff0c;并把新的连接放入全连接队列 查看全连接队列的命令 全连接队列满了…

Deep Learning Tuning Playbook(深度学习调参手册中译版)

前言 由五名研究人员和工程师组成的团队发布了《Deep Learning Tuning Playbook》&#xff0c;来自他们自己训练神经网络的实验结果以及工程师的一些实践建议&#xff0c;目前在Github上已有1.5k星。原项目地址本文为《Deep Learning Tuning Playbook》中文翻译版本&#xff0…

聊一聊微信小程序生命周期你最想知道的一些事

目录 前言 解析 运行机制 总结 前言 &#xff08;1&#xff09;为什么是微信小程序 最近有人问我一些关于微信小程序的问题&#xff0c;今天有时间也就整理了一些微信小程序的相关资料&#xff0c;给大家简单系统总结一些微信小程序的相关知识及生命周期。 &#xff08;2…

使用光泵磁力仪(OPMs)非接触测量视网膜活动

使用光泵磁力仪&#xff08;OPMs&#xff09;非接触测量视网膜活动摘要绪论方法2.1参与者和测量设置2.2刺激2.3数据分析结果讨论原文见&#xff1a; https://www.sciencedirect.com/science/article/pii/S1053811921008016 摘要 光泵磁力仪&#xff08;OPM&#xff09;已被用…

关于提升销量和排名,亚马逊、wish、ebay卖家该怎么做?

新年好&#xff0c;我是龙哥测评&#xff0c;在这里祝愿所有跨境朋友在新的一年里财源滚滚&#xff0c;一切顺利。 接下来龙哥就来说说&#xff0c;为什么店铺销量提升不上去&#xff0c;产品曝光低转化率低&#xff0c;产品有排名但是没销量&#xff0c;等等这些问题&#xf…

5 个我们仍可 Solana 在熊市危机报有希望的原因

Daniel, 2022 年 1 月前面&#xff0c;我们发表了 《9 大指标分析 Solana 的熊市危机》。当查看数据时&#xff0c;有一个很好的论据&#xff0c;即 Solana 在 2021/2022 年期间严重超卖&#xff0c;该网络没有项目、TVL 或用户来维持自己度过长期的熊市。它的崩溃只是更严重&a…

QT/C++——主窗口和事件处理

一、主窗口 上面就是一个主窗口&#xff0c;主窗口中的每一个都是Action 这次新建工程要选择mainwindow #ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow> #include <QAction> #include <QTextEdit> #include <QLabel> #include &l…

LeetCode 剑指 Offer 09. 用两个栈实现队列

题目 解题 这道题是用两个栈实现一个队列&#xff0c;具有一个队尾添加元素和队头删除元素的功能 这里思路是一个进&#xff0c;一个出&#xff0c;里面的元素顺序很关键&#xff0c;要保持一个进栈最先进的元素在另一个出栈的栈顶 第一种方法是&#xff0c;每次进元素&#x…

冰冰学习笔记:信号

欢迎各位大佬光临本文章&#xff01;&#xff01;&#xff01; 还请各位大佬提出宝贵的意见&#xff0c;如发现文章错误请联系冰冰&#xff0c;冰冰一定会虚心接受&#xff0c;及时改正。 本系列文章为冰冰学习编程的学习笔记&#xff0c;如果对您也有帮助&#xff0c;还请各位…

使用Postman快速访问MemFire Cloud应用

“超能力”数据库&#xff5e;拿来即用&#xff0c;应用开发人员再也不用为撰写API而发愁。MemFire Cloud 为开发者提供了简单易用的云数据库&#xff08;表编辑器、自动生成API、SQL编辑器、备份恢复、托管运维&#xff09;&#xff0c;很大地降低开发者的使用门槛。 使用Post…

关于保研(免试攻读硕士学位研究生)的相关政策

文章目录1、保研政策是什么&#xff1f;2、哪些学校可以保研&#xff1f;3、保研的流程/名额是怎样的&#xff1f;1、保研政策是什么&#xff1f; 什么是保研&#xff1f; 官方定义&#xff1a; 保研&#xff08;全称&#xff1a;推荐优秀应届本科毕业生免试攻读硕士学位研究…

Linux基础开发环境,yum 与 vim。

✅<1>主页&#xff1a;我的代码爱吃辣 &#x1f4c3;<2>知识讲解&#xff1a;Linux &#x1f525;<3>创作者&#xff1a;我的代码爱吃辣 &#x1f4ac;<4>前言&#xff1a;Linux必不可少的基础开发环境使用。 目录 一.Linux软件包管理器 yum &#x…

微电网经济优化运行(光伏、储能、柴油机)(Matlab代码实现)

&#x1f468;‍&#x1f393;个人主页&#xff1a;研学社的博客 &#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜…

液晶LCD1602驱动代码

液晶LCD1602简介LCD1602液晶显示器是广泛使用的一种字符型液晶显示模块。它是由字符型液晶显示屏&#xff08;LCD&#xff09;、控制驱动主电路HD44780及其扩展驱动电路HD44100&#xff0c;以及少量电阻、电容元件和结构件等装配在PCB板上而组成。不同厂家生产的LCD1602芯片可能…

《数据结构》二叉树(性质and遍历)

目录 ​编辑 树的定义 概念 树的定义 二叉树的概念 满二叉树 概念 完全二叉树 概念 二叉树的性质 二叉树的遍历 先序遍历 中序遍历 后序遍历 层序遍历 树的定义 概念 树是一种非线性的数据结构 树的定义 子树是不相交的除了根节点外&#xff0c;每个节点有且仅有一个…

360度客户视频的内容和四种数据类型

提到CRM客户管理系统&#xff0c;您是不是经常听到“360度客户视图”这个词&#xff1f;所谓360度客户视图&#xff0c;让企业做到全方位地建立客户认知&#xff0c;消除客户生命周期所有的信息脱节。下面来详细讲讲&#xff0c;Zoho CRM系统的360度客户视图是什么&#xff1f;…

统计分析工具

百度统计 百度统计访问地址 https://tongji.baidu.com/web/10000370440/homepage/index 创建项目及获取项目标识 1、创建分析网站 在管理页面中点击新增网站&#xff0c;填写完信息 2、获取代码 得到如下代码&#xff1a; <script> var _hmt _hmt || []; (function…