23.Merge k Sorted Lists (Array; Sort)

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;
    }
};
时间: 2024-08-29 16:34:59

23.Merge k Sorted Lists (Array; Sort)的相关文章

[LeetCode]23. Merge k Sorted Lists

23. Merge k Sorted Lists Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity. 给定k个排序了的链表,合并k个链表成一个排序链表. 本程序思路: 1)首先得到K个链表的长度和存在len中 2)从K个链表中找到值最小的那个节点,把该节点添加到合并链表中 3)重复len次即可把所有节点添加到合并链表中. 注意事项: 1)K个链表中有的

#23 Merge k Sorted Lists (N路归并排序)

#23 Merge k Sorted Lists (N路归并排序) 题目地址:#23 题目分类:链表/归并排序/堆排序 题目难度:hard 题目 Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity. 翻译:合并K个已经排序的链表,返回一个排序好的链表. 思路 暴力法,我们很容易想到:以一个for循环遍历所有的链表,找出最小的,然后将这个节点加入新的链表

23. Merge k Sorted Lists - LeetCode

Question 23.?Merge k Sorted Lists Solution 题目大意:合并链表数组(每个链表中的元素是有序的),要求合并后的链表也是有序的 思路:遍历链表数组,每次取最小节点 Java实现: public ListNode mergeKLists(ListNode[] lists) { ListNode preHead = new ListNode(0); ListNode minNode = getMinNode(lists); ListNode tmpNode =

23. Merge k Sorted Lists(js)

23. Merge k Sorted Lists Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity. Example: Input: [   1->4->5,   1->3->4,   2->6 ] Output: 1->1->2->3->4->4->5->6题意:按大小顺序合并n条链表代码

[Leetcode][Python]23: Merge k Sorted Lists

# -*- coding: utf8 -*-'''__author__ = '[email protected]' 23: Merge k Sorted Listshttps://oj.leetcode.com/problems/merge-k-sorted-lists/ Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity. ===Comments by

leetCode 23. Merge k Sorted Lists (合并k个排序链表) 解题思路和方法

Merge k Sorted Lists Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity. 思路:此题是由合并两个排序链表演化而来,刚开始,想法比较简单,像求最大公共前缀一样,逐一求解:但是最后超时,所以马上意识到出题方是为了使用归并和分治的方法,故重新写了代码. 代码一(超时未过): /** * Definition for singly-link

[LC] 23. Merge k Sorted Lists

Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity. Example: Input: [   1->4->5,   1->3->4,   2->6 ] Output: 1->1->2->3->4->4->5->6 Solution 1:Time: O(Nlgk)Space: O(N) * De

23. Merge K Sorted Lists (Java, 归并排序的思路)

题目:Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity. 解析:合并k个已经有序的单链表,使其最终成为一个有序的单链表.原理就是归并排序,递归运算.基本算法recusion 与 merge 编码: public ListNode mergeKLists(ListNode[] lists) { if(lists == null || lists.leng

[LeetCode] 23. Merge k Sorted Lists ☆☆

Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity. 解法1: 采用递归的方法,不管合并几个,归根到底还是需要两两合并. 首先想到的是前两个先合并,然后再跟第三个合并,然后第四个....但是这种做法效率不高. 换个思路,采用分治法,对数量超过2的任务进行拆分,直到最后只有一个或两个链表再进行合并.代码如下: /** * Definition for si