算法练习-删除链表的倒数第 N 个结点

51 阅读1分钟

题目

image.png

思路

看到倒数第N个这种题目,马上就想到的是双指针:

快指针比慢指针先跑N步,快慢指针再一起跑,待快指针到链表尾部,慢指针不就到末尾了嘛。

关键因素 题目是删除倒数第N个节点,那么单向链表删除节点必然是要获得被删除节点的前一个节点,然后: pNode->next = pNode->next->next;搞定。

这时候,就意味着需要把快指针先跑N+1N+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) {
        if (!head || (head->next == nullptr && n == 1)) { return nullptr; }

        ListNode vHead;
        vHead.next = head;
        ListNode* tail = &vHead;
        int count = 0;
        while (count++ < (n + 1)) {
            if (tail == nullptr) { break; }
            tail = tail->next;
        }
        ListNode* pDeleteNextLater = &vHead;
        while(tail != nullptr) {
            tail = tail->next;
            pDeleteNextLater = pDeleteNextLater->next;
        }
        pDeleteNextLater->next = pDeleteNextLater->next->next;
        return vHead.next;
    }
};