Home > Mobile >  Why do I get a error in leetcode submission but pass in IDE using the same code?
Why do I get a error in leetcode submission but pass in IDE using the same code?

Time:10-01

I am solving LeetCode question: enter image description here

Input: head = [1,2,2,1]
Output: true

Example 2:

enter image description here

Input: head = [1,2]
Output: false

Constraints:

  • The number of nodes in the list is in the range [1, 10⁵].
  • 0 <= Node.val <= 9

Follow up: Could you do it in O(n) time and O(1) space?

Using C I get the error below:

=================================================================
==42==ERROR: AddressSanitizer: heap-use-after-free on address 0x602000000098 at pc 0x00000037ac7d bp 0x7ffc1760fda0 sp 0x7ffc1760fd98
READ of size 8 at 0x602000000098 thread T0
    #2 0x7f5a8c3e70b2  (/lib/x86_64-linux-gnu/libc.so.6 0x270b2)
0x602000000098 is located 8 bytes inside of 16-byte region [0x602000000090,0x6020000000a0)
freed by thread T0 here:
    #3 0x7f5a8c3e70b2  (/lib/x86_64-linux-gnu/libc.so.6 0x270b2)
previously allocated by thread T0 here:......

Here is my code:

/*code only in VS 
#include <iostream>
using namespace std;
  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:

    bool isPalindrome(ListNode* head) {
        if (!head->next) {
            return true;
        }
        ListNode* slow = head;
        ListNode* fast = head;
        while (fast && fast->next) {
            fast = fast->next->next;
            slow = slow->next;
        }
        ListNode* prev = slow;
        ListNode* current = prev->next;
        while (current) {
            ListNode* temp = current->next;
            current->next = prev;
            prev = current;
            current = temp;
        }
        while (head != slow)
        {
            if (head->val != prev->val) {
                return false;
            }
            head = head->next;
            prev = prev->next;
        }
        return true;
    }
};
/*code only in VS 
int main()
{
    ListNode* a = new ListNode(1);
    ListNode* b = new ListNode(0);
    ListNode* c = new ListNode(3);
    ListNode* d = new ListNode(4);   //[1,0,3,4,0,1]
    ListNode* e = new ListNode(0);
    ListNode* f = new ListNode(1);
    a->next = b;
    b->next = c;
    c->next = d;
    d->next = e;
    e->next = f;
    Solution solution;
    cout << solution.isPalindrome(a);

}*/

I can run it and get the right answer in my IDE (Visual Studio 2019 Community), but get an error in the LeetCode submission.

Any idea why this would happen?

CodePudding user response:

The error occurs when the Leet Code test system will try to release the memory used by the previous test case, before launching the next one.

Your code leaves the list in a state where it will run in cycles: the node that follows slow has been rewired by your code to point back to slow.

We can imagine how the Leet Code clean-up code will free the node that slow refers to, then free the next node's memory, and then arrive again at slow which was already freed/deleted. This is the cause of this error. It is therefore important that you leave the list in a consistent state, where it has the original number of nodes, and there are no cycles.

To resolve the error quicly, just add this line before the last loop:

slow->next = nullptr;

However, this leaves the second (reversed) half of your list unreachable for Leet Code to clean up. That's not really fair (although fast). To do it properly, make slow stop at the left side of the center when the list size is even (by moving fast one step ahead), and then rewire the tail of the first half with the (new) head of the second half (which was reversed):

class Solution {
public:
    bool isPalindrome(ListNode* head) {
        if (!head->next) {
            return true;
        }
        ListNode* slow = head;
        ListNode* fast = head->next; // Stop loop sooner when size is even
        while (fast && fast->next) {
            fast = fast->next->next;
            slow = slow->next;
        }
        ListNode* prev = nullptr; // this will be assigned to the new tail
        ListNode* current = slow->next;
        while (current) {
            ListNode* temp = current->next;
            current->next = prev;
            prev = current;
            current = temp;
        }
        slow->next = prev; // link tail of first half to head of reversed part
        while (prev) // Continue the walk in second half until the list's end
        {
            if (head->val != prev->val) {
                return false;
            }
            head = head->next;
            prev = prev->next;
        }
        return true;
    }
};
  • Related