Sort List (LeetCode)
Question:
https://oj.leetcode.com/problems/sort-list/
解答:
排序基本上就是heapsort, mergesort和quicksort。因为是linked list而且不能用额外的空间,所以用mergesort,因为merge sort的合并可以in place进行。quicksort需要在index之间跳来跳去。
第一次在recursive函数里用了一个pointer,记录当前linked list后面接着的node。后来看了别人的解法,其实可以直接对head指针进行操作,每访问一次就head=head->next,这样子head永远是下一个要sort的子linked list的开始。
注意在head变成head->next后,原来的head->next需要设成NULL.
/** * 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) { int n = 0; ListNode* curr = head; while (curr) { n++; curr = curr->next; } if (n == 0) return NULL; return mergeSort(head, n); ListNode* nextNode = NULL; return mergeSort(head, n, nextNode); } ListNode* mergeSort(ListNode*& head, int n) { if (n == 1) { ListNode* newHead = head; head = head->next; newHead->next = NULL; return newHead; } ListNode* left = mergeSort(head, n/2); ListNode* right = mergeSort(head, n-n/2); ListNode* curr = NULL; ListNode* newHead = NULL; while (left || right) { bool leftFirst = false; if (left) leftFirst = (right ? left->val < right->val : true); else leftFirst = false; if (!curr) { curr = leftFirst ? left : right; newHead = curr; } else { curr->next = leftFirst ? left : right; curr = curr->next; } if (leftFirst) left = left->next; else right = right->next; } return newHead; } ListNode* mergeSort(ListNode* head, int n, ListNode*& nextNode) { if (n == 1) { nextNode = head->next; head->next = NULL; return head; } ListNode* left = mergeSort(head, n/2, nextNode); ListNode* right = mergeSort(nextNode, n-n/2, nextNode); ListNode* curr = NULL; while (left || right) { bool leftFirst = false; if (left) leftFirst = (right ? left->val < right->val : true); else leftFirst = false; if (!curr) { curr = leftFirst ? left : right; head = curr; } else { curr->next = leftFirst ? left : right; curr = curr->next; } if (leftFirst) left = left->next; else right = right->next; } return head; } };