Search code examples
c++linked-listruntime-errorsingly-linked-listfunction-definition

Why my code works in IDE with same testcases as in LeetCode, but in LeetCode this code does not work?


The problem on LeetCode: https://leetcode.com/problems/remove-nth-node-from-end-of-list/description/

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) {}
};

ListNode* removeNthFromEnd(ListNode* head, int n) {
    ListNode **buf = &head;
    for (int i = 0; i < n; ++i) {
        buf = &(*buf)->next;
    }
    (*buf) = (*buf)->next;
    return head;
}


int main() {
    removeNthFromEnd(new ListNode(1, new ListNode(2, new ListNode(3, new ListNode(4, new ListNode(5))))), 2);
    return 0;
}

Runtime Error Line 18: Char 26: runtime error: member access within null pointer of type 'ListNode' (solution.cpp) SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior prog_joined.cpp:27:26

I do not even know what I should try


Solution

  • Your function implementation has nothing common with deleting a node starting from the end of the list.

    This for loop

    for (int i = 0; i < n; ++i) {
        buf = &(*buf)->next;
    }
    

    counts nodes from the beginning of the list.

    Also it can invoke undefined behavior when the list contains less than n elements due to using a null pointer to access memory.

    And you need to delete the target node using the operator delete.

    The function can look the following way as shown in the demonstration program below.

    #include <iostream>
    
    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) {}
    };
    
    bool removeNthFromEnd( ListNode* &head, size_t n) 
    {
        bool success = n != 0;
    
        if ( success )
        {    
            ListNode *last = head;
        
            while (  last && n )
            {
                last = last->next;
                --n;
            }
    
            if ( ( success  = n == 0 ) )
            {
                ListNode **current = &head;
    
                while ( last )
                {
                    last = last->next;
                    current = &( *current )->next;
                }
    
                ListNode *tmp = *current;
                *current = ( *current )->next;
                delete tmp;
            }
        }
    
        return success;
    }
    
    
    std::ostream & display( const ListNode *head, std::ostream &os = std::cout )
    {
        for ( ; head != nullptr; head = head->next )
        {
            os << head->val << " -> ";
        }
    
        return os << "null";
    }
    
    
    int main() 
    {
        ListNode *head = new ListNode(1, new ListNode(2, new ListNode(3, new ListNode(4, new ListNode(5)))));
    
        display( head ) << '\n';
    
        removeNthFromEnd( head, 2);
    
        display( head ) << '\n';
    
       removeNthFromEnd( head, 4);
    
        display( head ) << '\n';
    
       removeNthFromEnd( head, 2);
    
        display( head ) << '\n';
    
        removeNthFromEnd( head, 1);
    
        display( head ) << '\n';
    
    
       removeNthFromEnd( head, 1);
    
        display( head ) << '\n';
    
       return 0;
    }
    

    The program output is

    1 -> 2 -> 3 -> 4 -> 5 -> null
    1 -> 2 -> 3 -> 5 -> null
    2 -> 3 -> 5 -> null
    2 -> 5 -> null
    2 -> null
    null