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;
}
相关推荐
Chandler241 小时前
LeetCode:DP-回文串问题
算法·leetcode·动态规划
hzxxxxxxx2 小时前
类和对象(上)
算法
Ctrl С2 小时前
[三分钟学算法]分治-快速排序-最小的K个数:设计一个算法,找出数组中最小的k个数。以任意顺序返回这k个数均可。
java·数据结构·算法·leetcode
xin007hoyo3 小时前
算法笔记.求约数
c++·笔记·算法
阿黄学技术3 小时前
ReentrantLock实现公平锁和非公平锁
java·开发语言·算法
汤姆_5113 小时前
【c语言】字符串函数
c语言·算法
_Itachi__3 小时前
LeetCode 热题 100 54. 螺旋矩阵
算法·leetcode·矩阵
柏木乃一3 小时前
平衡二叉搜索树模拟实现1-------AVL树(插入,删除,查找)
c++·学习·程序人生·算法·二叉搜索树·avl树·平衡二叉搜索树
智者知已应修善业4 小时前
【51单片机6位数码管显示时间与秒表】2022-5-8
c语言·c++·经验分享·笔记·单片机·算法·51单片机
八股文领域大手子4 小时前
第 7 篇:跳表 (Skip List):简单务实的概率性选手
java·数据结构·windows·算法·leetcode·链表·动态规划