【力扣-链表】5、删除链表的倒数第 N 个结点(19)

338 阅读1分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

19. 删除链表的倒数第 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]

图解

双指针:使用快慢指针来解决这个问题,快指针比慢指针先走n步(设置虚拟头节点),之后一起向后遍历,快指针指向最后一个节点时,慢指针指向节点的next节点就是待删除的节点。

image.png

CODE

#include <iostream>

using namespace std;

struct ListNode
{
    int val;
    ListNode *next;
    ListNode(int v) : val(v), next(nullptr){};
    ListNode(int v, ListNode *next) : val(v), next(next){};
};

class Solution
{
public:
    ListNode *removeNthFromEnd(ListNode *head, int n)
    {
        // 使用虚拟头节点,删除头节点时方便
        ListNode *dummpy = new ListNode(0, head);
        // 慢指针,指向待删节点的前驱节点
        ListNode *pre = dummpy;
        // 快指针,指向当前遍历的节点
        ListNode *cur = pre->next;
        // 快指针先走n步
        while (n--)
        {
            cur = cur->next;
        }
        // 遍历节点,快指针指向最后一个节点时,遍历完了所有节点
        // 慢指针此时指向了待删节点的前一个节点
        while (cur != nullptr)
        {
            cur = cur->next;
            pre = pre->next;
        }
        // 删除节点
        ListNode *tmp = pre->next;
        pre->next = tmp->next;
        delete tmp;

        // 返回头节点
        return dummpy->next;
    }

    void printListNode(ListNode *head)
    {
        ListNode *cur = head;
        while (cur)
        {
            cout << cur->val << " ";
            cur = cur->next;
        }
        cout << endl;
    }
};

int main()
{
    // 测试代码
    ListNode *head = new ListNode(1);
    ListNode *p1 = new ListNode(2);
    ListNode *p2 = new ListNode(3);
    ListNode *p3 = new ListNode(4);
    head->next = p1;
    p1->next = p2;
    p2->next = p3;

    Solution solu;
    ListNode *newHead = solu.removeNthFromEnd(head, 4);
    solu.printListNode(newHead);

    return 0;
}

image.png