为什么我在 leetcode 提交时出错,但使用相同的代码传入 IDE?

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

我正在解决LeetCode问题:234. Palindrome Linked List:

Given the head of a singly linked list, return true if it is a palindrome.

Example 1:

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

Example 2:

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?

使用 C++ 我得到以下错误:

=================================================================
==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:......

这是我的代码:

/*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);

}*/

我可以 运行 它并在我的 IDE(Visual Studio 2019 社区)中得到正确答案,但在 LeetCode 提交中出现错误。

知道为什么会这样吗?

当 Leet Code 测试系统在启动下一个测试用例之前尝试释放前一个测试用例使用的内存时,会发生错误。

您的代码使列表处于循环 运行 的状态:slow 之后的节点已被您的代码重新连接以指向 slow

我们可以想象 Leet Code 清理代码将如何释放 slow 引用的节点,然后释放下一个节点的内存,然后再次到达已经 slow freed/deleted。这是此错误的原因。因此,让列表保持一致状态很重要,它具有原始节点数,并且没有循环。

要快速解决错误,只需在最后一个循环之前添加此行:

slow->next = nullptr;

但是,这会使列表的后半部分(反向的)无法到达 Leet Code 进行清理。这不太公平(虽然很快)。要正确执行此操作,请在列表大小为偶数时使 slow 停在中心的左侧(通过将 fast 向前移动一步),然后用 (新)下半场头球(被逆转):

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