LeetCode 19. Remove Nth Node From End of List

19. Remove Nth Node From End of List

Difficulty: medium

Given a linked list, remove the n-th node from the end of list and return its head.

Example:

Given linked list: 1->2->3->4->5, and n = 2.

After removing the second node from the end, the linked list becomes 1->2->3->5.

Note:

Given n will always be valid.

Follow up:

Could you do this in one pass?

1st Version:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        vector<ListNode*> nodes;
        auto node = head;
        while (node != NULL) {
            nodes.push_back(node);
            node = node->next;
        }
        
        int po = nodes.size() - n;
        if (po - 1 < 0) {
            delete nodes[po];
            if (po + 1 <= nodes.size() - 1)
                head = nodes[po + 1];
            else 
                head = NULL;
        } else {
            delete nodes[po];
            if (po + 1 <= nodes.size() - 1)
                nodes[po - 1]->next = nodes[po + 1];
            else
                nodes[po - 1]->next = NULL;
        }
        return head;
    }
};

Rate:
Runtime: 4 ms, faster than 86.11% of C++ online submissions for Remove Nth Node From End of List.
Memory Usage: 8.8 MB, less than 6.58% of C++ online submissions for Remove Nth Node From End of List.

真是搞不懂我是什么弱智, 为什么要这么写, 还搞一个vector来存, 这样的话直接遍历两遍不就好了.

重写了一下, 时间和空间其实都已经达到预期了:
2nd Version:

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        size_t len = 0u;
        auto itr = head;
        while (itr != NULL) {
            itr = itr->next;
            ++len;
        }
        int po = len - n;
        itr = head;
        if (po == 0) {
            head = head->next;
            delete itr;
        } else {
            for (int i = 0; i < po - 1; ++i) {
                itr = itr->next;
            }
            auto newNext = itr->next->next;
            delete itr->next;
            itr->next = newNext;
        }
        return head;
    }
};

Rate:
Runtime: 4 ms, faster than 86.11% of C++ online submissions for Remove Nth Node From End of List.
Memory Usage: 8.4 MB, less than 98.68% of C++ online submissions for Remove Nth Node From End of List.

但是题目中叫我们挑战一遍拿到倒数第n个元素, 没经验, 想不出来.

3rd Version (Java):

// https://leetcode.com/problems/remove-nth-node-from-end-of-list/discuss/359826/Java-recursive-solution%3A-Runtime%3A-0-ms-faster-than-100.00-O(n)
class Solution {
    int cnt = 0;
    
    public int findN(ListNode current, int n) {
       
        if(current == null) {
            return (n + 1);
        }    
        n = findN(current.next, n);
        
        if(n != -1)
            n--;
        
        if(n == 0) {
            current.next = current.next.next;
            n = -1;
        }
        return n;
    }
    
    public ListNode removeNthFromEnd(ListNode head, int n) {
        
        int isDone = findN(head, n);
        
        if(isDone != -1) {
            head = head.next;
            return head;
        }
        return head;
    }
}

奇妙的方法, 递归. 不多解释了.