[LeetCode]day13 19.删除链表的倒数第n个结点

news/2025/2/5 22:51:04 标签: leetcode, 链表, 算法

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

题目描述

给你一个链表,删除链表的倒数第 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]

题解

解法一:使用两次遍历

思路

1.先通过一次遍历获得这个链表的长度size

2.通过size-n计算出移动到待删结点之前的结点数

3.再遍历使指针指向待删结点的前一个结点,

4.进行删除操作

自己先写:

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        if(!head)return NULL;
        ListNode*p=head;
        int size=0;
        while(p){
            size++;
            p=p->next;
        }
        p=head;
        for(int i=0;i<size-n;i++){
                p=p->next;
        }
        ListNode*q=p->next;
        p->next=q->next;
        delete q;
        return head;
    }
};

修改答案:

报错:

报错来自于删除操作: p->next=q->next;

我们没有考虑到一种情况就是 链表中要删的就是第一个节点

所以不存在移动到待删结点的前一个节点这种情况

所以我们可以加一个虚拟头结点,这样可以使操作统一

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        if(!head)return NULL;
       //添加虚拟头结点
        ListNode*dummy=new ListNode(0,head);
        //计算链表的大小
        ListNode*p=head;
        int size=0;
        while(p){
            p=p->next;
             size++;
        }
        //将结点移动到待删结点的前一个结点
        p=dummy;
        for(int i=0;i<size-n;i++){
                p=p->next;
        }
        //进行删除操作
        ListNode*q=p->next;
        p->next=q->next;
        delete q;
        return dummy->next;
    }
    
};

解法二:使用一次遍历

有没有方法可以实现只通过一次遍历,就能达到目的呢?

网上也有很多直接讲了快慢指针的方法 但是没有讲解为什么这样做就行了

快慢指针的原理

我们假设链表的长度为size,待删元素为倒数第n个元素

我们采用两个指针,一个为快指针,一个为慢指针

快指针先移动n步 即指向第n个元素 然后快慢指针一起移动 直到快指针指向最后一个元素

此时快指针移动了size-n个元素  

慢指针此时就指向了第size-n个元素,即倒数第n个元素的前一个元素


举个例 元素为1,2,3,4,5  n=2;

fast先移动两个元素的位置指向2 然后fast和slow一起移动直到fast指向最后一个元素 fast要移动三个元素 slow移动三个元素就是指向3 是倒数第二个元素前的一个元素

代码实现 

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        if(!head)return NULL;
        ListNode*dummy=new ListNode(0,head);
        ListNode*fast=dummy,*slow=dummy;
        //fast移动n个元素
        for(int i=0;i<n;i++){
            fast=fast->next;
        }
        //fast和slow一起移动size-n个元素的位置
        while(fast->next!=NULL){
            fast=fast->next;
            slow=slow->next;
        }
        //此时slow指向倒数第n个元素的前一个位置 进行删除操作
        ListNode* temp=slow->next;
        slow->next=temp->next;
        delete temp;
        return dummy->next;
    }
    
};


http://www.niftyadmin.cn/n/5842449.html

相关文章

pytorch线性回归模型预测房价例子

人工智能例子汇总&#xff1a;AI常见的算法和例子-CSDN博客 import torch import torch.nn as nn import torch.optim as optim import numpy as np# 1. 创建线性回归模型类 class LinearRegressionModel(nn.Module):def __init__(self):super(LinearRegressionModel, self).…

为AI聊天工具添加一个知识系统 之86 详细设计之27 数据处理:ETL

本文要点 ETL 数据提取 作为 数据项目的起点。数据的整个三部曲--里程碑式的发展进程&#xff1a; ETL : 1分形 Type()-层次Broker / 2完形 Method() - 维度Delegate /3 整形 Class() - 容器 Agent 1变象。变象 脸谱Extractor - 缠度&#xff08;物理 皮肤缠度&#xf…

04树 + 堆 + 优先队列 + 图(D1_树(D17_综合刷题练习))

目录 1. 二叉树的前序遍历&#xff08;简单&#xff09; 1.1. 题目描述 1.2. 解题思路 方法一&#xff1a;递归&#xff08;推荐使用&#xff09; 方法二&#xff1a;非递归&#xff08;扩展思路&#xff09; 2. 二叉树的中序遍历&#xff08;中等&#xff09; 2.1. 题目…

2025_1_31 C语言中关于数组和指针

1.数组作为指针传递 数组作为指针传递可以&#xff1a; 加一个数减一个数两个指针相减自增自减 int main() {int arr[] { 1,2,3,4,5,6,7,8,9 };printf("%d\n", arr[0] 2);printf("%d\n", arr[2] - 2);printf("%d\n", arr[0] arr[2]);int* …

Spring Security(maven项目) 3.0.3.0版本

前言&#xff1a; 通过实践而发现真理&#xff0c;又通过实践而证实真理和发展真理。从感性认识而能动地发展到理性认识&#xff0c;又从理性认识而能动地指导革命实践&#xff0c;改造主观世界和客观世界。实践、认识、再实践、再认识&#xff0c;这种形式&#xff0c;循环往…

Linux进程状态及其转换

在Linux系统中&#xff0c;进程是操作系统进行资源分配和调度的基本单位。每个进程在执行过程中会经历不同的状态&#xff0c;这些状态反映了进程当前的活动情况。通过top命令&#xff0c;我们可以实时查看系统中各个进程的状态。理解这些状态及其转换关系&#xff0c;对于系统…

基于RLS的自适应滤波器设计与Matlab实现

引言 自适应滤波器在信号处理领域具有重要应用&#xff0c;包括系统辨识、噪声消除和信道均衡等。递归最小二乘&#xff08;RLS&#xff09;算法因其快速收敛特性成为经典自适应算法之一。本文详细介绍RLS算法原理&#xff0c;并给出Matlab实现示例。 一、RLS算法原理 1.1 算…

Qt中的UIC、MOC、RCC宏定义说明

在Qt6新建工程的时候&#xff0c;CMakeLists.txt中会默认带有UIC&#xff0c;MOC&#xff0c;RCC的3个宏定义。 set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) uic(User Interface Compiler)&#xff0c;用户界面编译器&#xff0c;将根据.ui文件生成相…