码迷,mamicode.com
首页 > 其他好文 > 详细

23.Merge k Sorted Lists (Array; Sort)

时间:2015-08-11 20:47:38      阅读:121      评论:0      收藏:0      [点我收藏+]

标签:

Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.

思路I: 选择排序

每次都比较各个list的头指针所指的val,取最小的那个。时间复杂度O(n2)

Result:Time Limit Exceeded

 

思路II: 最小堆。

时间复杂度:堆排序其实也是一种选择排序。只不过直接选择排序中,为了从R[1...n]中选择最大记录,需比较n-1次,然后从R[1...n-2]中选择最大记录需比较n-2次。事实上这n-2次比较中有很多已经在前面的n-1次比较中已经做过,而树形选择排序恰好利用树形的特点保存了部分前面的比较结果,因此可以减少比较次数。时间复杂度为O(nlogn)

堆排序思想参考:http://jingyan.baidu.com/article/5225f26b057d5de6fa0908f3.html 

class Solution {
public:
    ListNode *mergeKLists(vector<ListNode *> &lists) {
        // 使用堆排序, 
        // 1. 选出每个链表的头来插入小顶堆中,
        // 2. 再把堆顶接入合并链表中,
        // 3. 被选出的指针后移再加入小顶堆中,回到2
        // 4. 最后所有链表都为空时,返回合并链表的头指针
        if(lists.empty()) return nullptr;
        vector<ListNode* > heap;
        heap.push_back(0); //padding
        // 1. 选出每个链表的头来插入小顶堆中,
        for(int i = 0; i != lists.size(); i ++){
           if(lists[i]) heap.push_back(lists[i]);
        }
        makeHeap(heap);
        // 2. 再把堆顶接入合并链表中,
        ListNode head(-1); // 合并链表的表头
        ListNode* p = &head;
        while(heap.size()>1){
            auto minNode = heap[1];
            p->next = minNode; // 接入链表
            p = p->next;
            // 3. 被选出的指针后移再加入小顶堆中,回到2
            auto next = minNode->next;
            if(next) {
                heap[1] = next;
            }else{
                swap(heap[1], heap[heap.size()-1]);
                heap.pop_back();
            }
            minHeap(heap, 1);//加入新元素到堆顶后,自上向下调整
        }
        // 4. 最后所有链表都为空时,返回合并链表的头指针
        return head.next;
    }
    // 建立小顶堆
    // 自底向上
    void makeHeap(vector<ListNode*> &heap){
        // 从最后一个元素的父节点开始建立小顶堆
        for(int i = (heap.size()-1)/2; i >0 ; i --){
            minHeap(heap, i);
        }
    }
    // 小顶堆,以第i个元素为根建立小顶堆
    //位置从1开始,取元素时记得-1
    // 自顶向下
    void minHeap(vector<ListNode*> &heap, int i){
        int l = i*2;
        int r = l+1;
        int least(i);
        // 算出最小元素的位置
        if((l< heap.size()) && heap[l]->val<heap[i]->val ){
            // 如果没有超过边界并且左孩子比父亲小,则换
            least = l;
        }
        if(r<heap.size() && heap[r]->val<heap[least]->val){
            // 如果没有超过边界并且右孩子最小,则换
            least = r;
        }
        if(least != i){
            swap(heap[i], heap[least]);
            minHeap(heap, least);//换了之后,继续向下调整
        }
    }
};

 

 

思路III:归并排序

初始状态:6,202,100,301,38,8,1
第一次归并后:{6,202},{100,301},{8,38},{1},比较次数:3;
第二次归并后:{6,100,202,301},{1,8,38},比较次数:4;
第三次归并后:{1,6,8,38,100,202,301},比较次数:4;
reference: http://baike.baidu.com/link?url=ayX3MQx_CrmcjOxkL7EKhXukLH9pJKJsD1XDMaP6eQwvFfc-BtnQBUTsElRafXbxqhCFOIlKC5VsL14LgjEjIK 
归并排序时间复杂度O(nlogn)
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */

class Solution {
public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        if(lists.empty()) return NULL;
        
        mergeSort(lists, 0, lists.size()-1);
        return lists[0];
    }
    void mergeSort(vector<ListNode*>& lists, int start, int end){
        if(start==end) return;
        int mid = (start + end) >> 1;
        mergeSort(lists, start, mid);
        mergeSort(lists, mid+1, end); 
        merge(lists,start, mid+1);
    }
    
    void merge(vector<ListNode*>& lists, int lst1, int lst2){
        ListNode* root = NULL;
        ListNode* current = NULL;
        
        while(lists[lst1] && lists[lst2]){
            if(lists[lst1]->val <= lists[lst2]->val){
                if(!root){
                    root = lists[lst1];
                    current = root;
                }
                else{
                    current->next = lists[lst1];
                    current = current->next;
                }
                lists[lst1] = lists[lst1]->next;
            }
            else{
                if(!root){
                    root = lists[lst2];
                    current = root;
                }
                else{
                    current->next = lists[lst2];
                    current = current->next;
                }
                lists[lst2] = lists[lst2]->next;
            }
        }
        
        while(lists[lst1]){
            if(!root){
                root = lists[lst1];
                current = root;
            }
            else{
                current->next = lists[lst1];
                current = current->next;
            }
            lists[lst1] = lists[lst1]->next;
        }
        while(lists[lst2]){
            if(!root){
                root = lists[lst2];
                current = root;
            }
            else{
                current->next = lists[lst2];
                current = current->next;
            }
            lists[lst2] = lists[lst2]->next;
        }
        
        lists[lst1] = root;
    }
};

 

23.Merge k Sorted Lists (Array; Sort)

标签:

原文地址:http://www.cnblogs.com/qionglouyuyu/p/4721853.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!