【LeetCode刷题】删除链表的倒数第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

解法思路

  1. 虚拟头节点 :创建dummy节点指向原链表头,避免删除头节点时的特殊处理(如输入head=[1], n=1的情况)。
  2. 双指针初始化fastslow都从dummy开始。
  3. 快指针先行 :让fast先向前走n步,拉开与slow的距离。
  4. 同步移动指针fastslow同时前进,直到fast到达链表末尾(fast.nextNone)。此时slow的下一个节点,就是链表的倒数第 N 个节点
  5. 删除节点 :将slow.next指向slow.next.next,完成节点删除。

核心优势

  • 时间复杂度 O (L):仅遍历链表一次(L 为链表长度),比 "先统计长度再删除" 的两次遍历更高效。
  • 边界全覆盖:通过虚拟头节点,完美处理 "删除头节点""链表长度为 1" 等特殊情况。

Python代码

python 复制代码
# 导入必要的类型注解模块
from typing import Optional


# 完整定义单链表节点类
class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

    # 可选:添加打印链表的辅助方法(方便测试)
    def __str__(self):
        result = []
        current = self
        while current:
            result.append(str(current.val))
            current = current.next
        return " -> ".join(result)


# 核心解题类
class Solution:
    def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
        # 虚拟头节点:避免删除头节点时的边界处理
        dummy = ListNode(0)
        dummy.next = head
        fast = dummy
        slow = dummy

        # 步骤1:快指针先向前走n步
        for _ in range(n):
            fast = fast.next

        # 步骤2:快慢指针同时前进,直到快指针到达链表末尾
        while fast.next:
            fast = fast.next
            slow = slow.next

        # 步骤3:删除慢指针的下一个节点(倒数第n个节点)
        slow.next = slow.next.next

        # 返回新的头节点(虚拟头节点的下一个)
        return dummy.next


# 辅助函数:将列表转换为链表(方便测试)
def list_to_linkedlist(arr):
    if not arr:
        return None
    head = ListNode(arr[0])
    current = head
    for val in arr[1:]:
        current.next = ListNode(val)
        current = current.next
    return head


# 测试用例
if __name__ == "__main__":
    # 测试用例1:常规情况
    arr1 = [1, 2, 3, 4, 5]
    n1 = 2
    head1 = list_to_linkedlist(arr1)
    print("原链表1:", head1)
    solution = Solution()
    new_head1 = solution.removeNthFromEnd(head1, n1)
    print(f"删除倒数第{n1}个节点后:", new_head1)  # 预期输出:1 -> 2 -> 3 -> 5

    # 测试用例2:删除头节点
    arr2 = [1, 2]
    n2 = 2
    head2 = list_to_linkedlist(arr2)
    print("\n原链表2:", head2)
    new_head2 = solution.removeNthFromEnd(head2, n2)
    print(f"删除倒数第{n2}个节点后:", new_head2)  # 预期输出:2

    # 测试用例3:链表只有一个节点
    arr3 = [1]
    n3 = 1
    head3 = list_to_linkedlist(arr3)
    print("\n原链表3:", head3)
    new_head3 = solution.removeNthFromEnd(head3, n3)
    print(f"删除倒数第{n3}个节点后:", new_head3)  # 预期输出:None

LeetCode提交代码

python 复制代码
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
        # 虚拟头节点:避免删除头节点时的边界处理
        dummy = ListNode(0)
        dummy.next = head
        fast = dummy
        slow = dummy
        
        # 步骤1:快指针先向前走n步
        for _ in range(n):
            fast = fast.next
        
        # 步骤2:快慢指针同时前进,直到快指针到达链表末尾
        while fast.next:
            fast = fast.next
            slow = slow.next
        
        # 步骤3:删除慢指针的下一个节点
        slow.next = slow.next.next
        
        # 返回新的头节点(虚拟头节点的下一个)
        return dummy.next

程序运行结果展示

原链表1: 1 -> 2 -> 3 -> 4 -> 5

删除倒数第2个节点后: 1 -> 2 -> 3 -> 5

原链表2: 1 -> 2

删除倒数第2个节点后: 2

原链表3: 1

删除倒数第1个节点后: None

总结

本文介绍了一种高效删除链表倒数第N个节点的双指针解法。通过创建虚拟头节点处理边界情况,使用快慢指针实现一次遍历:快指针先走N步,然后两指针同步移动直至链表末尾,此时慢指针的下一个节点即为待删除节点。该方法时间复杂度O(L)(L为链表长度),优于两次遍历的解法,且能完美处理删除头节点等特殊情况。文中提供了Python实现代码,包含链表转换、测试用例及运行结果验证,确保算法正确性和鲁棒性。该解法已通过LeetCode测试,适用于所有合法输入情况。

相关推荐
冷雨夜中漫步6 小时前
Python快速入门(6)——for/if/while语句
开发语言·经验分享·笔记·python
郝学胜-神的一滴7 小时前
深入解析Python字典的继承关系:从abc模块看设计之美
网络·数据结构·python·程序人生
百锦再7 小时前
Reactive编程入门:Project Reactor 深度指南
前端·javascript·python·react.js·django·前端框架·reactjs
颜酱8 小时前
图结构完全解析:从基础概念到遍历实现
javascript·后端·算法
m0_736919108 小时前
C++代码风格检查工具
开发语言·c++·算法
yugi9878388 小时前
基于MATLAB强化学习的单智能体与多智能体路径规划算法
算法·matlab
喵手8 小时前
Python爬虫实战:旅游数据采集实战 - 携程&去哪儿酒店机票价格监控完整方案(附CSV导出 + SQLite持久化存储)!
爬虫·python·爬虫实战·零基础python爬虫教学·采集结果csv导出·旅游数据采集·携程/去哪儿酒店机票价格监控
2501_944934738 小时前
高职大数据技术专业,CDA和Python认证优先考哪个?
大数据·开发语言·python
helloworldandy8 小时前
使用Pandas进行数据分析:从数据清洗到可视化
jvm·数据库·python
DuHz8 小时前
超宽带脉冲无线电(Ultra Wideband Impulse Radio, UWB)简介
论文阅读·算法·汽车·信息与通信·信号处理