0

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

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
Чмоня
  • 31
  • 1
  • 4
    *I do not even know what I should try* - [Debug](https://stackoverflow.com/questions/25385173/what-is-a-debugger-and-how-can-it-help-me-diagnose-problems) your code. – PaulMcKenzie Apr 03 '23 at 21:12
  • 1
    @Чмоня Your function removeNthFromEnd has nothing common with removing an element from the end of the list.:) – Vlad from Moscow Apr 03 '23 at 21:17
  • 1
    Did you recently program in LISP? – Thomas Matthews Apr 03 '23 at 21:19
  • From what I remember, LeetCode has its own `main` program hidden from you. So your home-made `main` program may not even look anything like the hidden `main` that Leetcode is producing. – PaulMcKenzie Apr 03 '23 at 21:19
  • Leetcode is going to hit your code with all manner of evil inputs deliberately trying to break it. If your test set is even remotely friendly you'll likely miss some of the dirty tricks the Leetcode judge will pull. – user4581301 Apr 03 '23 at 21:19
  • Leetcode has also turned on the Undefined Behavior Sanitizer. If you have not also done this (usually by adding `-fsanitize=undefined` to the compiler command line), you deserve the butt kicking you're about to get. Use all of the tools at your disposal BEFORE you submit the code for testing. For want it's worth, build with `-Wall -Wextra -Werror -fsanitize=undefined,address` to improve your odds of catching problems early. – user4581301 Apr 03 '23 at 21:22
  • I think you missed the fact that n counts from 1, not from 0, so you traverse too far if n is the length of the list. – molbdnilo Apr 04 '23 at 06:43

1 Answers1

0

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
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335