LeetCode 148 排序链表
题目:
在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序。
示例 1:
输入: 4->2->1->3 输出: 1->2->3->4
示例 2:
输入: -1->5->3->4->0 输出: -1->0->3->4->5
解题思路:
可达到O(nlogn)的排序我们知道有三种,堆排、快排、二路归并。 这里由于是链表,堆排和归并都不太容易操作。所以这里我们用二路归并算法。
二路归并有递归的和非递归的,这里单链表,用非递归较为简单。因为递归要比较两个区间的大小,这里需要用到双指针。
代码:
1 /** 2 * Definition for singly-linked list. 3 * struct ListNode { 4 * int val; 5 * ListNode *next; 6 * ListNode(int x) : val(x), next(NULL) {} 7 * }; 8 */ 9 class Solution { 10 public: 11 ListNode* sortList(ListNode* head) { 12 if(head == NULL) 13 return NULL; 14 ListNode *p = head; 15 int len = 0; 16 while(p) { 17 len++; 18 p = p->next; 19 } 20 21 ListNode *temp = new ListNode(0); 22 temp->next = head; 23 24 int interval; 25 for(interval = 1; interval <= len; interval *= 2) { //从下往上归并 26 27 ListNode *pre = temp; 28 ListNode *first = temp->next; 29 ListNode *second = temp->next; 30 31 while(first && second) { 32 int i = 0; 33 while(i < interval && second) { 34 second = second->next; 35 i++; 36 } 37 int fvisit = 0; 38 int svisit = 0; 39 while(fvisit < interval && svisit < interval && first && second) { 40 if(first->val < second->val) { //前指针较小,则把前指针装入放在前头 41 pre->next = first; 42 pre = first; 43 first = first->next; 44 fvisit++; 45 } 46 else { 47 pre->next = second; 48 pre = second; 49 second = second->next; 50 svisit++; 51 } 52 } 53 while(fvisit < interval && first) {//剩下的较大的就依次接上就好 54 pre->next = first; 55 pre = first; 56 first = first->next; 57 fvisit++; 58 } 59 while(svisit < interval && second) { 60 pre->next = second; 61 pre = second; 62 second = second->next; 63 svisit++; 64 } 65 pre->next = second; //往后继续直到第一次排序结束 66 first = second; 67 } 68 } 69 ListNode *ans = temp->next; 70 delete temp; 71 return ans; 72 } 73 };