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

目录

题目

解法一

双指针算法

核心思想

执行流程

具体例子

代码

解法二

两次遍历法

核心思想

执行流程

具体例子

代码


题目

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

解法一

双指针算法

核心思想

利用双指针间隔固定距离(n+1),当快指针到达链表末尾时,慢指针恰好位于倒数第n个节点的前一位置。

执行流程

  1. 创建哑节点dummy,指向链表头部
  2. 初始化快指针fast和慢指针slow,都指向dummy
  3. fast先前进n+1步
  4. fast和slow同时前进,直到fast到达NULL
  5. slow此时指向待删除节点的前一节点,执行删除操作
  6. 返回dummy->next作为新的头节点

具体例子

对于链表1→2→3→4→5,删除倒数第2个节点(n=2):

  1. 创建dummy→1→2→3→4→5
  2. fast和slow初始都指向dummy
  3. fast前进3步(n+1):fast指向3
  4. fast和slow同时前进:
  5. 当fast到达5后的NULL
  6. slow指向3
  7. 删除slow->next(即4):3→5
  8. 返回dummy->next:1→2→3→5

代码

cpp 复制代码
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* dummy = new ListNode(0);
        dummy->next = head;

        ListNode* fast = dummy;
        ListNode* slow = dummy;

        for(int i = 0; i<n+1; i++)
        {
            if(!fast)
            {
                return head;
            }
            fast = fast->next;
        }

        while(fast)
        {
            fast = fast->next;
            slow = slow->next;
        }

        if(slow->next)
        {
        ListNode* toDelete = slow->next;
        slow->next = slow->next->next;

        delete toDelete;
        }

        ListNode* newhead = dummy->next;
        delete dummy;
        return newhead;
    }
};

解法二

两次遍历法

核心思想

执行流程

  1. 创建哑节点dummy,指向链表头部
  2. 第一次遍历计算链表长度length
  3. 计算待删除节点的正序位置:position = length - n
  4. 第二次遍历,前进position步找到待删除节点的前驱
  5. 删除目标节点
  6. 返回dummy->next作为新的头节点

具体例子

对于链表1→2→3→4→5,删除倒数第2个节点(n=2):

  1. 创建dummy→1→2→3→4→5
  2. 计算链表长度length = 5
  3. 找到正序位置:position = 5 - 2 = 3
  4. 从dummy开始前进3步到达节点3
  5. 删除节点3的下一个节点(4):3→5
  6. 返回dummy->next:1→2→3→5

双指针法效率更高,因为只需一次遍历;两次遍历法思路更直观,易于理解。

代码

cpp 复制代码
ListNode* removeNthFromEnd(ListNode* head, int n) {
    // 创建哑节点
    ListNode* dummy = new ListNode(0);
    dummy->next = head;
    
    // 第一次遍历计算链表长度
    int length = 0;
    ListNode* first = head;
    while (first) {
        length++;
        first = first->next;
    }
    
    // 计算要删除节点的位置
    int position = length - n;
    
    // 找到待删除节点的前一个节点
    ListNode* curr = dummy;
    for (int i = 0; i < position; i++) {
        curr = curr->next;
    }
    
    // 删除节点并释放内存
    ListNode* toDelete = curr->next;
    curr->next = curr->next->next;
    delete toDelete;
    
    // 获取新的头节点
    head = dummy->next;
    delete dummy;
    
    return head;
}
相关推荐
Тиё Сиротака2 小时前
红包分配算法的严格数学理论与完整实现
算法
potato_may3 小时前
链式二叉树 —— 用指针构建的树形世界
c语言·数据结构·算法·链表·二叉树
java修仙传4 小时前
每日一题,力扣560. 和为 K 的子数组
算法·leetcode
ada7_4 小时前
LeetCode(python)——148.排序链表
python·算法·leetcode·链表
点云SLAM4 小时前
点云配准算法之-Voxelized GICP(VGICP)算法
算法·机器人·gpu·slam·点云配准·vgicp算法·gicp算法
资深web全栈开发6 小时前
LeetCode 3625. 统计梯形的数目 II
算法·leetcode·组合数学
橘颂TA6 小时前
【剑斩OFFER】算法的暴力美学——外观数列
算法·leetcode·职场和发展·结构与算法
Liangwei Lin6 小时前
洛谷 P1434 [SHOI2002] 滑雪
算法
c#上位机6 小时前
halcon图像增强之自动灰度拉伸
图像处理·算法·c#·halcon·图像增强
rit84324996 小时前
压缩感知信号恢复算法:OMP与CoSaMP对比分析
数据库·人工智能·算法