为什么我在 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;
}
};
我正在解决LeetCode问题:234. Palindrome Linked List:
Given the
head
of a singly linked list, returntrue
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 andO(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;
}
};