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;
    }
}
相关推荐
Jsundoku1 小时前
第六章 机器学习 -- 支持向量机
算法·机器学习·支持向量机
?abc!1 小时前
(数组)448. 找到所有数组中消失的数字
算法
淡海水1 小时前
05-03-源码-Boehm GC分配与碎片管理
开发语言·算法·unity·c#·游戏引擎·gc
青少儿编程课堂2 小时前
蓝桥杯·全国青少年信息素养大赛·电子学会Python/C/C++考级:任意进制互转与大数多进制加法解析
c++·python·算法·bfs·信息学竞赛
多弗朗皮卡丘2 小时前
C++ 哈希(下)
c++·算法·哈希算法
aichitang20242 小时前
Meta Muse Spark Open:816B 巨型开放权重多模态 Agent 模型架构、部署实战与社区首测全解
大数据·人工智能·python·算法·ai·架构·spark
Coder-magician3 小时前
图论总结篇
算法·图论
有同事要进步3 小时前
Leecode第68题:x的平方根
java·数据结构·算法
吹什么轩3 小时前
linux系统复习:进程优先级与O(1)调度
java·linux·算法