leetcode 链接:删除链表的倒数第 N 个结点

题目

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


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

示例:
[中等] 19. 删除链表的倒数第 N 个结点 - 图1

  1. 输入:head = [1,2,3,4,5], n = 2
  2. 输出:[1,2,3,5]

解答 & 代码

快指针先走 n 步,然后快慢指针同时走,直到快指针的 next 指向空,此时慢指针指向倒数第 k+1 个节点,删除倒数第 k 个节点

时间复杂度 O(N),空间复杂度 O(1)

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        // 特殊情况:如果头节点为空或者 n<1 (n 代表要删除倒数第 n 个节点),不删除,直接返回原头节点
        if(head == nullptr || n < 1)
            return head;

        ListNode* dummyHead = new ListNode(-1, head);    // 虚拟头节点
        ListNode* fast = dummyHead;        // 快指针
        ListNode* slow = dummyHead;        // 慢指针
        // 快指针先走 n 步
        for(int i = 0; i < n; ++i)
        {
            if(fast == nullptr)        // 如果快指针走到空,说明 n 大于链表长度,因此不删除直接返回
                return head;
            fast = fast->next;
        }
        // 快慢指针同时走,快指针的next走到空,代表慢指针走到倒数第 k+1 个节点
        while(fast->next != nullptr)
        {
            fast = fast->next;
            slow = slow->next;
        }
        // 此时 slow 走到倒数第 k-1 个节点
        ListNode* kNode = slow->next;    // 倒数第 k 个节点
        slow->next = kNode->next;
        delete kNode;                    // 删除倒数第 k 个节点

        return dummyHead->next;
    }
};

执行结果:

执行结果:通过

执行用时:4ms, 在所有 C++ 提交中击败了 82.82% 的用户
内存消耗:10.5 MB, 在所有 C++ 提交中击败了 20.71% 的用户