首页 > 其他分享 >19.删除链表的倒数第N个节点

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

时间:2023-11-29 11:35:16浏览次数:38  
标签:结点 19 fast next 链表 second 节点 倒数第

leetcode题目链接

题目描述

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

示例 1:

19.删除链表的倒数第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]

提示:

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

思路

在对链表进行操作时,一种常用的技巧是添加一个哑结点(dummy node),它的next指针指向链表的头结点。这样就不需要对头结点进行特殊的判断。

例如,在本题中,如果要删除节点y,需要知道节点y的前驱节点x,并将x的指针指向y的后继节点。但由于头结点不存在前驱节点,在删除头结点时需要进行特殊判断。但如果添加了哑结点,那么头节点的前驱节点就是哑结点本身,此时只考虑通用情况即可。

方法一:计算链表长度

首先从头节点开始对链表进行一次遍历,得到链表的长度L。随后再从头结点开始对链表进行一次遍历,当遍历到第L-n+1个节点时,就找到了要删除的节点。

为了方便删除操作,可以从哑结点开始遍历L-n+1个节点。当遍历到第L-n+1个节点时,它的下一个节点就是需要删除的节点,这样只需要修改一次指针,就能完成删除操作。

代码略。

时间复杂度:O(L)

空间复杂度:O(1)

方法二:栈

在遍历链表的同时将所有节点依次入栈。根据栈【先进后出】的原则,弹出栈的第n个节点就是需要删除的节点,并且栈顶的节点就是待删除节点的前驱节点。

代码略。

时间复杂度:O(L)

空间复杂度:O(L)

方法三:双指针

以上两种方法一种多次遍历了链表,一种空间复杂度与链表长度有关。

可以使用两个指针first和second同时对链表进行遍历,并且first比second超前n个节点。当first遍历到链表的末尾时,second就恰好处于倒数第n个节点。

具体地,初始时first和second均指向头结点。首先使用first对链表进行遍历,遍历的次数为n。此时,first和second之间间隔了n-1个节点,即first比second超前了n个节点。在此之后,同时使用first和second对链表进行遍历。当first遍历到链表的末尾(即first为空指针)时,second恰好指向倒数第n个节点。

如果能够得到倒数第n个节点的前驱节点而不是倒数第n个节点的话,删除操作会更加方便。因此可以考虑在初始时将second指向哑结点,其余的操作步骤不变。这样一来,当first遍历到链表的末尾时,second的下一个节点就是需要删除的节点。

如果second初始指向head,写出的代码如下,可以看到需要有一个pre节点指向second的前驱节点:

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode tmpHead = new ListNode();
        tmpHead.next = head;
        ListNode pre = tmpHead;
        ListNode fast = head, low = head;
        for (int i = 0; i < n && fast != null ;i++){
            fast = fast.next;
        }
        while (fast != null) {
            fast = fast.next;
            low = low.next;
            pre = pre.next;
        }
        pre.next = low.next;
        return tmpHead.next;
    }
}

如果second初始指向哑结点,写出的代码如下,不需要额外的节点记录前驱节点:

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode tmpHead = new ListNode();
        tmpHead.next = head;
        ListNode fast = head, low = tmpHead;
        for (int i = 0; i < n && fast != null ;i++){
            fast = fast.next;
        }
        while (fast != null) {
            fast = fast.next;
            low = low.next;
        }
        low.next = low.next.next;
        return tmpHead.next;
    }
}

标签:结点,19,fast,next,链表,second,节点,倒数第
From: https://blog.51cto.com/u_16357390/8612955

相关文章

  • 软件设计实验19:中介者模式
    实验19:中介者模式本次实验属于模仿型实验,通过本次实验学生将掌握以下内容: 1、理解中介者模式的动机,掌握该模式的结构;2、能够利用中介者模式解决实际问题。 [实验任务一]:虚拟聊天室在“虚拟聊天室”实例中增加一个新的具体聊天室类和一个新的具体会员类,要求如下:1.新的具......
  • CF1900D - Small GCD 题解
    1900D-SmallGCD给定序列\(A\),定义\(f(a,b,c)\)为\(a,b,c\)中最小的次小的数的\(\gcd\),求:\[\sum_{i=1}^n\sum_{j=i+1}^n\sum_{k=j+1}^nf(a_i,a_j,a_k)\]题解目前来说有两种方法,都十分有启发意义,但是有共同的开头。考虑到\(A\)的顺序实际上没有......
  • P1955 [NOI2015] 程序自动分析
    P1955[NOI2015]程序自动分析基本思路考虑到了不等号的不可传递性,所以决定只开相等的并查集。然后突发奇想,觉得可以在找父亲的过程中判断是不是冲突。然而这样就不能路径压缩,显然超时。并且,根本没看清楚数据范围,实际上这题的数很大,裸开数组会爆炸。这是一开始的代码#inclu......
  • 拉链表学习
    拉链表介绍:记录历史。记录一个事务从开始,一直到当前状态的所有变化的信息。业务场景表中的部分字段会被更新。需要查看某一个时间点或者时间段的历史快照信息。表中的记录变化的比例和频率不是很大。具体案例......
  • 冒泡排序:要比较(二层循环)n*(n-1)(第一层循环)次,最大的在最后,最次大的在倒数第二,
    privatestatic voidsort(int[]w,intl,intr){//冒泡排序要比较n二层循环*(n-1)次,第一层循环      for(inti=r;i>l;i--){        for(intj=l;j<i;j++){          if(w[j]>w[j+1])          { ......
  • Oracle Database 19c 创建只读用户
    1.登录oracle数据库服务器,以管理员用户登录sqlplus/assysdba切换容器等操作showpdbs; altersessionsetcontainer=ORA19CPDB;showcon_name;2.创建只读用户createusercmsreadonlyidentifiedbycmsreadonlydefaulttablespaceCMSPROD_DATA......
  • SP19543 GSS8 - Can you answer these queries VIII 题解
    更好的阅读体验SP19543GSS8-CanyouanswerthesequeriesVIIIfhq+二项式定理。提供一个不太一样的思路。默认下标从\(1\)开始。首先插入删除,区间查询,想到可以平衡树维护或者离线下来做线段树。本文中是用的是fhq,好写一些。\(k\)非常的小,考虑对于每一个\(k\)的答......
  • AP5192pwm调光温度保护内置mos管恒流芯片
    产品描述AP5192是一款PWM工作模式,高效率、外围简单、内置功率MOS管,适用于4.5-100V输入的高精度降压LED恒流驱动芯片。最大电流1.5A。AP5192可实现线性调光和PWM调光,线性调光脚有效电压范围0.55-2.6V.AP5192工作频率可以通过RT外部电阻编程来设定,同时内置抖频电路,可以降低对......
  • 刷题复习(一)链表-双指针
    刷题复习(一)链表-双指针https://labuladong.gitee.io/algo/di-ling-zh-bfe1b/shuang-zhi-0f7cc/1、合并两个有序链表思路清晰,双链表有个根节点记录开头/***Definitionforsingly-linkedlist.*publicclassListNode{*intval;*ListNodenext;*ListNode(){}......
  • 219. 存在重复元素 II
    你一个整数数组nums和一个整数k,判断数组中是否存在两个不同的索引i和j,满足nums[i]==nums[j]且abs(i-j)<=k。如果存在,返回true;否则,返回false。示例1:输入:nums=[1,2,3,1],k=3输出:true>代码classSolution{public:boolcontainsNearbyD......