Leetcode148. 排序链表 中遇到的错误
分类: 链表
难度: 中等
情况: /*
备注: set比较器的写法;归并排序
tags:
- leetcode
链接:148. 排序链表
代码
解法一:multiset
/*** Definition for singly-linked list.* 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:struct cmp { // set的比较器需要是一个类型bool operator() (const ListNode *a, const ListNode *b) const {return a->val < b->val;}};ListNode* sortList(ListNode* head) {ListNode *dumyhead = new ListNode(0);dumyhead->next = head;// set<ListNode *, cmp> s; // set不允许重复元素multiset<ListNode *, cmp> s;ListNode *cur = head;while (cur) {s.insert(cur);cur = cur->next;}cur = dumyhead;for (auto t:s) {cout << t->val << " ";cur->next = t;cur = cur->next;}// 断尾!cur->next = nullptr; // 一定要加,防止形成环或访问已释放内存return dumyhead->next;}
};
解法二:归并排序
/*** Definition for singly-linked list.* 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:ListNode* sortList(ListNode* head) {if (!head || !head->next) return head;ListNode *fast = head, *slow = head;while (fast->next && fast->next->next) {fast = fast->next->next;slow = slow->next;}ListNode *left = head, *right = slow->next;// cout << left->val << " " << right->val << endl;slow->next = nullptr; // 断开链表left = sortList(left);right = sortList(right);// cout << left->val << " " << right->val << endl;return merge(left, right);}ListNode* merge(ListNode *l1, ListNode *l2) {ListNode *newhead = new ListNode(0);ListNode *cur = newhead;while (l1 && l2) {if (l1->val < l2->val) {cur->next = l1;l1 = l1->next;}else {cur->next = l2;l2 = l2->next;}cur = cur->next;}cur->next = l1 ? l1 : l2;return newhead->next;}
};
题解
set自定义比较器
struct cmp { // set的比较器需要是一个类型bool operator() (const ListNode *a, const ListNode *b) const {return a->val < b->val;}};set<ListNode *, cmp> s;
遇到的错误
-
set不允许重复元素,要用multiset
Line 14: Char 22: error: function cannot return function type 'bool (const ListNode *, const ListNode *)'14 | bool oeprator() (const ListNode *a, const ListNode *b) {| ^
竟然是operator拼错了…
In file included from prog_joined.cpp:1:
In file included from ./precompiled/headers.h:50:
In file included from /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/map:62:
/usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/bits/stl_tree.h:768:8: error: static assertion failed due to requirement 'is_invocable_v<const Solution::cmp &, ListNode *const &, ListNode *const &>': comparison object must be invocable as const759 | is_invocable_v<const _Compare&, const _Key&, const _Key&>,| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
operator结尾没写const
Line 81: Char 9:
=================================================================
==21==ERROR: AddressSanitizer: heap-use-after-free on address 0x502000000078 at pc 0x5573084da1d6 bp 0x7ffd9b2b5ba0 sp 0x7ffd9b2b5b98
READ of size 8 at 0x502000000078 thread T0#0 0x5573084da1d5 in __ListNodeUtils__::freeList(ListNode*&) (solution+0x1ab1d5)#1 0x5573084b8738 in main solution.cpp:81:9#2 0x7f4075b2c1c9 (/lib/x86_64-linux-gnu/libc.so.6+0x2a1c9) (BuildId: 6d64b17fbac799e68da7ebd9985ddf9b5cb375e6)#3 0x7f4075b2c28a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+
heap-use-after-free
代码里没有断开链表尾节点的next
指针。在你用multiset
重新连接链表节点时,需要显式断开尾节点的next
,否则链表可能成环或者访问悬空指针。
原链表节点顺序被打乱,尾节点的next
可能指向原链表中间某个节点,形成环。
dumyhead也最好使用局部变量ListNode dummyhead(0);
Line 46: Char 14: runtime error: member access within null pointer of type 'ListNode' (solution.cpp)
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior prog_joined.cpp:55:14
ListNode* merge(ListNode *l1, ListNode *l2) {ListNode *newhead = new ListNode(0);ListNode *cur = newhead->next;while (l1 && l2) {if (l1->val < l2->val) {cur = l1;l1 = l1->next;}else {cur = l2;l2 = l2->next;}cur = cur->next;}cur->next = l1 ? l1 : l2;return newhead->next;}
这段代码的问题出在: ListNode *cur = newhead->next;
这里把 cur
初始化为 newhead->next
,但此时 newhead->next
是 nullptr
,导致你在后续执行 cur->next = ...
时,相当于对空指针解引用,触发了 Undefined Behavior(未定义行为)。
if (!head || !head->next) return nullptr;
这行的意思是:如果链表为空 或者 只有一个节点,就返回空指针。
但实际上,链表只有一个节点时就是排序好了的,应该返回这个节点本身,而不是 nullptr。
优化
还可以把递归改成迭代优化空间复杂度