leetcode-148 Sort List

递归解法:本来mergesort需要O(n)的空间复杂度,但这里是链表,所以只需要O(1)的空间复杂度

要求时间复杂度为O(nlogn),那么不能用quickSort了(最坏O(n^2)),所以使用mergeSort.

通常写排序算法都是基于数组的,这题要求基于链表。所以需要自己设计函数获得middle元素,从而进行切分。

参考Linked List Cycle II中的“龟兔赛跑”思想:兔子前进两步,龟前进一步,从而可以获得middle元素

注意获取中间节点:需要三个指针:fast slow pre(pre指向slow的上一个位置,可以举两个节点的例子进行带入考虑,如果不适用pre会出错)

<span style="font-family:Microsoft YaHei;font-size:14px;">/**
 * 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;
        ListNode *middle = getMiddle(head);
        ListNode *head2 = middle->next;
        middle->next = NULL;
        
        return merge(sortList(head),sortList(head2));
        
    }
    
    ListNode *getMiddle(ListNode *head){
        ListNode *fast = head,*slow = head,*pre = NULL;
        while(fast && fast->next){
            fast = fast->next->next;
            pre = slow;
            slow = slow->next;
        }
        return pre;
    }
    
    ListNode *merge(ListNode *first,ListNode *second){
        if(first == NULL) return second;
        if(second == NULL) return first;
        ListNode helper(0);
        ListNode *work = &helper;
        while(first && second){
            if(first->val <= second->val){
                work->next = first;
                first = first->next;
            }else{
                work->next = second;
                second = second->next;
            }
            work = work->next;
        }
        
        if(first) work->next = first;
        if(second) work->next = second;
        
        return helper.next;
    }
};</span>


参考:http://www.cnblogs.com/ganganloveu/p/3763707.html


非递归解法:

Nice problem. I use a non-recurisve way to write merge sort. For example, the size of ListNode is 8,

Round #1 block_size = 1

(a1, a2), (a3, a4), (a5, a6), (a7, a8)

Compare a1 with a2, a3 with a4 ...

Round #2 block_size = 2

(a1, a2, a3, a4), (a5, a6, a7, a8)

merge two sorted arrays (a1, a2) and (a3, a4), then merge tow sorted arrays(a5, a6) and (a7, a8)

Round #3 block_size = 4

(a1, a2, a3, a4, a5, a6, a7, a8)

merge two sorted arrays (a1, a2, a3, a4), and (a5, a6, a7, a8)

No need for round #4 cause block_size = 8 >= n = 8

<span style="font-family:Microsoft YaHei;font-size:14px;">/**
 * 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;
        int n = countList(head),iter = 0,blockSize = 1,a = 0,b = 0;
        ListNode *A,*B,*it,*last,*tmp;
        ListNode helper(0); //排序可能会打乱第一个结点(head)的顺序,所以需要一个辅助节点
        last = &helper;
        last->next = head;
        
        while(blockSize < n){
            iter = 0;
            it = helper.next;
            last = &helper;   //last为排序时候的工作节点
            
            while(iter < n){
                a = min(n - iter,blockSize);
                b = min(n - iter - a,blockSize);
                A = it;  //待排序的第一个块的第一个结点
                
                if(b != 0){
                    for(int i = 0; i < a - 1; i++) it = it->next;
                    B = it->next;
                    it->next = NULL;
                    it = B;  //待排序的第二个块(和A相邻的块)的第一个结点
                    
                    for(int j = 0; j < b - 1; j++) it = it->next;
                    tmp = it->next;
                    it->next = NULL;
                    it = tmp;
                }
                
                while(A || B){
                    if(B == NULL || ( A != NULL && A->val <= B->val)){
                        last->next = A;
                        A = A->next;
                    }else{
                        last->next = B;
                        B = B->next;
                    }
                    last = last->next;
                }
                last->next = NULL;
                iter += a + b;   //iter为已经排序的节点个数
            }
            blockSize <<= 1;
        }
        return helper.next;
    }
    
    int countList(ListNode *head){
        int n = 0;
        while(head){
            n++;
            head = head->next;
        }
        return n;
    }
};</span>

参考:https://leetcode.com/discuss/10264/my-o-n-log-n-time-o-1-space-solution


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值