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

leetcode.cn/problems/re...

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

示例 1:

ini 复制代码
输入: head = [1,2,3,4,5], n = 2
输出: [1,2,3,5]

示例 2:

ini 复制代码
输入: head = [1], n = 1
输出: []

示例 3:

ini 复制代码
输入: head = [1,2], n = 1
输出: [1]

提示:

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

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

双指针的经典应用,如果要删除倒数第n个节点,让fast移动n步,然后让fast和slow同时移动,直到fast指向链表末尾。删掉slow所指向的节点就可以了。

思路是这样的,但要注意一些细节。

分为如下几步:

  • 首先这里我推荐大家使用虚拟头结点,这样方便处理删除实际头结点的逻辑,如果虚拟头结点不清楚,可以看这篇: 链表:听说用虚拟头节点会方便很多?
  • 定义fast指针和slow指针,初始值为虚拟头结点,如图:
  • fast首先走n + 1步 ,为什么是n+1呢,因为只有这样同时移动的时候slow才能指向删除节点的上一个节点(方便做删除操作),如图:
  • fast和slow同时移动,直到fast指向末尾,如题: //图片中有错别词:应该将"只到"改为"直到"
  • 删除slow指向的下一个节点,如图:
kotlin 复制代码
class Solution {
    fun removeNthFromEnd(head: ListNode?, n: Int): ListNode? {
        //新建一个虚拟头节点指向head
        val dummyNode = ListNode(0)
        dummyNode.next = head
        //快慢指针指向虚拟头节点
        var fastNode: ListNode? = dummyNode
        var slowNode: ListNode? = dummyNode

        // 只要快慢指针相差 n 个结点即可
        for (i in 0..<n) {
            fastNode = fastNode?.next
        }

        while (fastNode?.next != null) {
            fastNode = fastNode.next
            slowNode = slowNode?.next
        }

        // 此时 slowIndex 的位置就是待删除元素的前一个位置。
        // 具体情况可自己画一个链表长度为 3 的图来模拟代码来理解
        slowNode?.next = slowNode.next?.next

        return dummyNode.next
    }
}
  • 时间复杂度: O(n)
  • 空间复杂度: O(1)

递归解法:

java 复制代码
class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        // 创建一个新的哑节点,指向原链表头  
        ListNode s = new ListNode(-1, head);
        // 递归调用remove方法,从哑节点开始进行删除操作  
        remove(s, n);
        // 返回新链表的头(去掉可能的哑节点)  
        return s.next;
    }
    
    public int remove(ListNode p, int n) {
        // 递归结束条件:如果当前节点为空,返回0  
        if (p == null) {
            return 0;
        }
        // 递归深入到下一个节点  
        int net = remove(p.next, n);
        // 如果当前节点是倒数第n个节点,进行删除操作  
        if (net == n) {
            p.next = p.next.next;  
        }
        // 返回当前节点的总深度  
        return net + 1;
    }
}
相关推荐
不会就选b1 小时前
算法日常・每日刷题--<贪心>25
数据结构·算法
千里码aicood4 小时前
基于CART算法的图书分类系统设计与实现
数据库·算法·分类
做cv的小昊5 小时前
【World Model】π0.5:a Vision-Language-Action Model with Open-World Generalization
人工智能·算法·机器学习·大模型·多模态·vla·世界模型
لا معنى له5 小时前
World-In-World: World Models in a Closed-Loop World
算法
Discipline10297 小时前
尼泊尔河流流量:天气驱动的预测与高流量风险
人工智能·算法
XuCoder8 小时前
改一个数,右边全得重算,这题怎么扛住两万次查询
算法
小羊没烦恼!8 小时前
在Scrum中实施敏捷建模
java·开发语言·windows·算法·c#
weixin_307779138 小时前
基于睿擎工业开发平台的预训练视觉模型轻量化适配与低代码部署优化
开发语言·算法
hold?fish:palm9 小时前
45 二叉树的右视图
开发语言·c++·算法