算法力扣刷题记录十【19.删除链表的倒数第N个节点】

news2024/9/21 11:03:47

前言

链表练习,继续
题目:力扣【19.删除链表的倒数第N个节点】


题目阅读

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

示例 1:
在这里插入图片描述

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

示例 2:

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

示例 3:

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

提示:

链表中结点的数目为 sz
1 <= sz <= 30
0 <= Node.val <= 100
1 <= n <= sz

进阶:

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

第一次尝试

先不考虑进阶,看如何实现。

思路:重点是什么找到倒数第n个节点。

  • 删除节点操作:用cur指向被删除节点的前一个节点。所以肯定得要一个虚拟头节点
  • 初始:cur = dummy_node;判断cur是不是在删除目标的前一个节点的位置?
  • 用search = cur,将search后移n位,看search->next是否为空:
    • n=1,将cur位置后移1位,search->next==nullptr;
    • n=2,将cur位置后移2位,search->next==nullptr;
    • n=3,将cur位置后移3位,search->next==nullptr;
    • 依次类推

代码实现(测试通过)

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
            ListNode* dummy_node = new ListNode(0,head);
            ListNode* cur = dummy_node;

            while(cur->next != nullptr){
                ListNode* search = cur;
                for(int i=0;i < n ;i++){
                    search = search->next;
                }
                if(search->next == nullptr){
                    //交换
                    ListNode* tmp = cur->next;
                    cur->next = cur->next->next;
                    delete tmp;
                    break;
                }
                cur = cur->next;
            }

            head = dummy_node->next;
            delete dummy_node;
            return head;
    }
};

检查:head=nullptr,符合逻辑。n=1,for循环条件判断正确。所以通过测试。
分析时间复杂度

while循环最差情况要遍历整个链表长度,for循环最差情况下执行n*(n+1)/2次,所以整体时间复杂度O(n^3)。

进阶

尝试使用一趟扫描。
思路:同样是线性结构,数组里面有快慢指针。这里能不能也用快慢指针?类似滑动窗口?

代码实现

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
            ListNode* dummy_node = new ListNode(0,head);
            ListNode* slow = dummy_node;
            ListNode* fast = dummy_node->next;
            int num = 1;//计数链表总长度

            if(slow->next != nullptr){
                while(fast->next != nullptr){
                    fast = fast->next;
                    num++;
                }
                if(num < n ){	//完善n超出链表长度,此时不删除,返回原链表,抛出异常
                	throw out_of_range("n > list_length");
                	return head;
                }
                
                for(int i = 0;i < num-n ;i++){
                    slow = slow->next;
                }
                ListNode* tmp = slow->next;
                slow->next = slow->next->next;
                delete tmp;
            }

            head = dummy_node->next;
            delete dummy_node;
            return head;
    }
};

思路正确:

  • 让fast先找到链表的最后一个元素,同时计数num,得到链表的总元素。
  • 收缩窗口,移动slow,移动num-n次,指向删除目标的前一个节点。slow到达位置之后,开始链表删除操作。

思路来源:个人博客【算法力扣刷题记录四【长度最小的子数组】】,学习到滑动窗口,同样是线性规则,所以借来使用。

进阶成功!!!


代码随想录学习

学习内容

同样是定义fast和slow,但过程也有区别。
我的操作:fast直接走到链表结尾,得出链表节点总数,再让slow后移num-n,到达删除目标的前一个位置。
参考操作

  • fast先走n步,这样窗口内包含n个节点,再让fast和slow同时移动,窗口内始终保持n个节点,当fast=nullptr时,slow恰好指向倒数第n个节点。
  • 由于删除操作,需要slow指向倒数第(n+1)个节点,所以修正让fast先走n+1步.

代码实现:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
            ListNode* dummy_node = new ListNode(0,head);
            ListNode* slow = dummy_node;
            ListNode* fast = dummy_node;

            while(fast != nullptr  && n >= 0){ //n >= 0确保fast先走了n+1步
                fast = fast->next;
                n--;
            }
            if(n < 0){  //如果输入的n大于链表长度,n<0才算fast走到位,否则fast没走到位,但又已经到达链表尾部。返回原链表,不操作。不然就会把头节点删除,因为slow没有移动。
                while (fast != nullptr ){
                fast = fast->next;
                slow = slow->next;
                }
                ListNode* tmp = slow->next;
                slow->next = slow->next->next;
                delete tmp;
            }else{			//当n输入超过链表长度,抛出异常。
            	throw out_of_range("n out of list range");
			}
            
            

            head = dummy_node->next;
            delete dummy_node;
            return head;
    }
};

参考答案在第11行有操作空指针的风险,只是力扣用例没有检出来。
所以我在if(n < 0)可以保证输入的n小于链表长度,更完善。如果输入n超过链表长度,抛出out_of_range异常

可以回过头看[进阶]目录下代码完善。


总结

  • 删除链表节点:加虚拟头结点
  • “滑动窗口”思路:个人和参考,两种操作。
  • 代码随想录参考11行,个人认为有缺陷,没有保证n小于链表长度,作了补充。

(欢迎指正,转载标明出处)

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

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

相关文章

使用Anaconda Prompt安装cv2模块

问题 使用命令&#xff1a; conda install opencv-python出现找不到包 使用命令&#xff1a;pip install opencv-python下载很慢&#xff08;kb/s速度&#xff09;而且会由于断连报错&#xff08;不一定是网的问题&#xff09; 解决方案 使用清华镜像下载&#xff0c;这样…

逆变器使用手册:类型详解、安装要点与维护须知

逆变器随着可再生能源的兴起和移动电源需求的激增已成为连接直流电与交流电世界的桥梁&#xff0c;其重要性不言而喻。无论是太阳能发电系统的高效利用&#xff0c;还是汽车、游艇等移动设备的电力供应&#xff0c;逆变器都扮演着关键角色。然而&#xff0c;正确的使用方法是确…

3D在线展览馆的独特魅力,技术如何重塑展览业的未来?

在数字化和虚拟现实技术迅猛发展的今天&#xff0c;3D在线展览馆已经成为一种颇具前景的创新形式。搭建3D在线展览馆不仅能够突破传统展览的时空限制&#xff0c;还能为参观者提供身临其境的体验&#xff0c;极大地提升展示效果和用户互动。 一、3D在线展览馆的意义 1、突破时空…

idea 自动生成序列化数字

目标&#xff1a;当类继承Serializable后自动生成序列化Uid 网上查了很多说勾选class without ‘serialVersionUID’ 但是我勾选没用 最后发现&#xff0c;我勾选的是Serialization issues里面的配置&#xff0c;要勾选的是JVM languages下的 如下图所示&#xff0c;记录一下…

鸿蒙期末项目(2)

主界面 主界面和商店详情界面参考如下设计图&#xff08;灵感严重匮乏&#xff09; 简单起见&#xff0c;将整个app分为4个布局&#xff0c;分别是主界面、搜索界面、购物车界面&#xff0c;以及个人界面。 所以在app中也需要使用tab组件进行分割&#xff0c;且需要通过tabBa…

笔记本电脑录屏,教你3个方法,简单录屏

随着科技的飞速发展&#xff0c;笔记本电脑录屏功能已经不再局限于传统的录制需求&#xff0c;而是成为了探索屏幕动态的新方式。无论是创意工作者、游戏爱好者还是日常办公者&#xff0c;都可以借助这一功能&#xff0c;将屏幕上的精彩瞬间、重要信息或创新思路记录下来&#…

Quads,一个无敌的 Python 库!

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com 大家好&#xff0c;今天为大家分享一个无敌的 Python 库 - Quads。 Github地址&#xff1a;https://github.com/fogleman/Quads 在科学计算和工程应用中&#xff0c;数值积分是一个常见的问题。Python的Quads库…

maven仓库的作用以及安装 , DEA配置本地Maven

ay12-maven 主要内容 Maven的作用Maven仓库的作用Maven的坐标概念Maven的安装IDEA配置本地Maven 一、maven概述 1.1、项目开发中的问题 1、我的项目依赖一些jar包&#xff0c;我把他们放在哪里&#xff1f;直接拷贝到项目的lib文件夹中?如果我开发的第二个项目还是需要上面…

【独家揭秘】SmartEDA电路仿真软件:电子电路基础学习的神器!

在电子科技日新月异的今天&#xff0c;电路基础学习的重要性愈发凸显。但你是否曾为复杂的电路图、难以理解的电路原理而感到困扰&#xff1f;今天&#xff0c;我要向大家推荐一款学习神器——SmartEDA电路仿真软件&#xff0c;让你轻松踏入电子电路基础学习的殿堂&#xff01;…

pytorch为自己的extension backend添加profiler功能

pytorch为自己的extension backend添加profiler功能 1.参考文档2.your-extension-for-pytorch需要增加的代码3.pytorch demo及如何调整chrome trace json文件4.[可视化](https://ui.perfetto.dev/) 本文演示了pytorch如何为自己的extension backend添加profiler功能 背景介绍 …

HarmonyOS Next开发学习手册——代码混淆

代码混淆简介 针对工程源码的混淆可以降低工程被破解攻击的风险&#xff0c;缩短代码的类与成员的名称&#xff0c;减小应用的大小。 DevEco Studio提供代码混淆的能力并默认开启&#xff0c;API 10及以上版本的Stage模型、 编译模式为release 时自动进行代码混淆。 使用约束…

React_创建一个项目

目录 一、React&#xff08;js 版&#xff09; 二、React&#xff08;ts 版&#xff09; 使用react创建一个项目,前提是确保你已经安装了Node.js和npm。 如果没有安装Node.js和npm&#xff0c;查看这个文件&#xff1a; 安装node.js和npmhttps://blog.csdn.net/zxy1993106…

Arcgis地统计分析工具灰色不可用 解决方法

使用Arcmap&#xff0c;调用地统计分析工具&#xff08;Geostatistical Analyst&#xff09;下的探索数据&#xff08;Explore Data&#xff09;&#xff0c;发现工具呈灰色不可用。这是由于扩展模块中没有将该模块做勾选设置导致的。下面介绍一下如何解决地统计分析工具不可用…

学生成绩管理系统带8000字文档学生选课管理系统java项目javaweb项目ssm项目jsp项目java课程设计java毕业设计

文章目录 学生选课成绩管理系统一、项目演示二、项目介绍三、8500字项目文档四、部分功能截图五、部分代码展示六、底部获取项目源码带8500字文档&#xff08;9.9&#xffe5;带走&#xff09; 学生选课成绩管理系统 一、项目演示 选课成绩管理系统 二、项目介绍 语言: Java …

【从0实现React18】 (五) 初探react mount流程 完成核心递归流程

更新流程的目的&#xff1a; 生成wip fiberNode树标记副作用flags 更新流程的步骤&#xff1a; 递&#xff1a;beginWork归&#xff1a;completeWork 在 上一节 &#xff0c;我们探讨了 React 应用在首次渲染或后续更新时的整体更新流程。在 Reconciler 工作流程中&#xff…

硬盘空间告急?监控服务器容量,钉钉及时提醒!

在日常的服务器维护中&#xff0c;硬盘容量的监控是非常重要的。如果硬盘容量超过某个阈值&#xff0c;可能会导致服务器无法正常运行&#xff0c;影响业务的正常运作。为了避免这种情况&#xff0c;我们可以编写一个Shell脚本&#xff0c;定期检查硬盘容量&#xff0c;当超过设…

springboot + Vue前后端项目(第二十记)

项目实战第二十记 写在前面1. 高德地图官网2. 开发文档3. 集成高德地图3.1 在public文件夹下创建config.js3.2 index.html&#xff08;在项目启动文件中引入外部的js&#xff09;3.3 点标记&#xff08;用点标记当前位置&#xff09;3.4 信息窗体&#xff08;点击当前位置&…

如何预防和处理他人盗用IP地址?

IP地址的定义及作用 解释 IP 地址在互联网中的作用。它是唯一标识网络设备的数字地址&#xff0c;类似于物理世界中的邮政地址。 1、IP地址盗窃的定义 解释一下什么是IP地址盗用&#xff0c;即非法使用他人的IP地址或者伪造IP地址的行为&#xff0c;这种行为可能引发法律和安…

DLMS/COSEM协议—(Green-Book)Gateway protocol

DLMS/COSEM协议 — Gateway protocol 10.10 Gateway protocol &#xff08;网关协议&#xff09;10.10.1 概述10.10.2 网关协议 &#xff08;The gateway protocol&#xff09;10.10.3 HES在WAN/NN中作为发起者&#xff08;拉取操作&#xff09;10.10.4 LAN中的终端设备作为发起…

数据库物理结构设计-定义数据库模式结构(概念模式、用户外模式、内模式)、定义数据库、物理结构设计策略

一、引言 如何基于具体的DBMS产品&#xff0c;为数据库逻辑结构设计的结果&#xff0c;即关系数据库模式&#xff0c;制定适合应用要求的物理结构 1、在设计数据库物理结构前&#xff0c;数据库设计人员首先 要充分了解所用的DBMS产品的功能、性能和特点&#xff0c;包括提供…