算法内容
本文件实现 LeetCode 148「排序链表」。核心思路是对单链表做归并排序,利用链表切分和有序链表合并完成排序。
split 使用快慢指针找到链表中点,并断开为左右两段;sortList 递归排序左右子链表;merge 使用虚拟头节点把两个有序链表合并。归并排序适合链表结构,因为合并时只需要调整指针,不需要随机访问。时间复杂度为 O(n log n),递归栈空间复杂度为 O(log n)。
算法实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
|
#include <vector> #include <iostream> #include <stack> #include <queue> #include <algorithm> #include <unordered_map> 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) {} }; using namespace std; class Solution { public: ListNode *sortList(ListNode *head) { ListNode *left, *right; int len = split(head, &left, &right); if (len > 2) { left = sortList(left); right = sortList(right); } return merge(left, right); }
ListNode *merge(ListNode *left, ListNode *right) { ListNode *head = new ListNode(0), *tmp; tmp = head; while (left != nullptr && right != nullptr) { if (left->val < right->val) { tmp->next = left; left = left->next; } else { tmp->next = right; right = right->next; } tmp = tmp->next; } if (left != nullptr) { tmp->next = left; } if (right != nullptr) { tmp->next = right; } tmp = head->next; return tmp; }
int split(ListNode *head, ListNode **left, ListNode **right) { ListNode *v = new ListNode(0); v->next = head; ListNode *slow = v, *fast = v; int len = 0; while (fast->next != nullptr) { slow = slow->next; fast = fast->next; len++; if (fast->next != nullptr) { fast = fast->next; len++; } } *left = head; *right = slow->next; slow->next = nullptr; return len; } };
|