Problem : Sort a linked list in O(n log n) time using constant space complexity.
两个解法,一个是递归的,一个是迭代的;不过递归终归还是使用了log n的栈空间,是否满足题意要看怎么认定题目要求了。 有任何其他好的解法,或者对本文解法有任何看法,都非常欢迎讨论,谢谢。
1.
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *sortList(ListNode *head) {
if (head == NULL || head->next == NULL) return head;
// 解法1 - 递归归并
/*
ListNode *l = NULL, *r = NULL;
splitList(head, l, r);
l = sortList(l);
r = sortList(r);
return mergeList(l, r);
*/
// 解法2 -- 非递归归并
int len = 0;ListNode *hi = head;
while (hi != NULL) {
len++;
hi = hi->next;
}
ListNode dummy(-1);
dummy.next = head;
for (int step = 1; step < len; step <<= 1) {
int dstep = (step << 1);
hi = &dummy;
for (int j = 0; j < len; j += dstep) {
ListNode *pre = hi, *lo = hi->next, *mo = hi;
for (int j = 0; j < step && mo->next != NULL; j++) {
if (hi->next != NULL) hi = hi->next;
if (hi->next != NULL) hi = hi->next;
mo = mo->next;
}
if (mo == hi) break;
listMerge(pre, lo, mo, hi);
}
}
return dummy.next;
}
private:
void listMerge(ListNode *pre, ListNode *lo, ListNode *mo, ListNode *&hi) {
if (pre == NULL || lo == NULL || mo == NULL) return;
ListNode *m1 = mo->next, *next = hi->next;
mo->next = NULL;
while (lo != NULL && m1 != next) {
if (lo->val <= m1->val) {
pre->next = lo;
lo = lo->next;
} else {
pre->next = m1;
m1 = m1->next;
}
pre = pre->next;
}
if (lo == NULL) {
pre->next = m1;
} else {
pre->next = lo;
mo->next = next;
}
while (pre->next != next) pre = pre->next;
hi = pre;
}
void splitList(ListNode *head, ListNode *&l, ListNode *&r) {
l = head;
r = NULL;
if (head == NULL || head->next == NULL) return;
ListNode *lo = head, *hi = head->next;
while (hi != NULL && hi->next != NULL) {
hi = hi->next->next;
if (hi != NULL) lo = lo->next;
}
r = lo->next;
lo->next = NULL;
}
ListNode* mergeList(ListNode *l, ListNode *r) {
ListNode dummy(-1);
ListNode *pre = &dummy;
while (l != NULL && r != NULL) {
if (l->val <= r->val) {
pre->next = l;
l = l->next;
} else {
pre->next = r;
r = r->next;
}
pre = pre->next;
}
pre->next = (l == NULL ? r : l);
return dummy.next;
}
};