LintCode 104: Merge K Sorted Lists (经典题!)

这题非常经典。
有4种解法。

  1. k个指针,每个指向一个list。每次比较k个指针的对应元素,取最小值,同时相应指针后移一位。如此反复直到所有list为空。
    缺点是太慢,时间复杂度为O(k*N),N为所有元素。
    代码如下:
/**
 * Definition of ListNode
 * class ListNode {
 * public:
 *     int val;
 *     ListNode *next;
 *     ListNode(int val) {
 *         this->val = val;
 *         this->next = NULL;
 *     }
 * }
 */
class Solution {
public:
    /**
     * @param lists: a list of ListNode
     * @return: The head of one sorted list.
     */
    ListNode *mergeKLists(vector<ListNode *> &lists) {
        int listsSize = lists.size();
        
        if (listsSize == 0) return nullptr;
        
        ListNode dummy(ListNode(0));
        ListNode *result = &dummy;
        ListNode *head = result;
        
        vector<ListNode *> listPtrs(listsSize);
        set <int> s;
        
        for (int i = 0; i < listsSize; ++i) {
            s.insert(i);
            listPtrs[i] = lists[i];
        }
        
        while (!s.empty()) {
            
            int index = *(s.begin());
            int minVal = INT_MAX;
            if (listPtrs[index]) minVal = listPtrs[index]->val;
            for (auto i : s) {
                if (listPtrs[i]) {
                    if (listPtrs[i]->val <= minVal) { //note: should be <= here
                        index = i;
                        minVal = listPtrs[i]->val;
                    }
                } else {
                  s.erase(i);
                }
            }
            
            result->next = listPtrs[index];
            result = result->next; 
            if (listPtrs[index]) listPtrs[index] = listPtrs[index]->next;
         }
        
        return head->next;
    }
};

注意:
if (listPtrs[i]->val <= minVal) 这里必须用<= 而不是<,不过没想明白为什么<就不对?

看了一下网上类似的代码,发现我的代码较繁琐,其中的set和listPtrs[]都可以不用 ,用一个count就可以了。

2刷:还是繁琐

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        int n = lists.size();
        ListNode * dummyHead = new ListNode(INT_MAX);
        vector<ListNode*> p(n);
        for (int i = 0; i < n; ++i) {
            p[i] = lists[i];
        }
        ListNode *candidate;
        int smallest_value = INT_MAX, smallest_index = -1;
        for (int i = 0; i < n; ++i) {
            if (lists[i] && lists[i]->val <smallest_value) {
                smallest_value = lists[i]->val;
                smallest_index = i;
            }
        }
        if (smallest_index == -1) return NULL;
        candidate = lists[smallest_index];
        dummyHead->next = candidate;
        lists[smallest_index] = lists[smallest_index]->next;
        
        while (1) {
            smallest_value = INT_MAX, smallest_index = -1;
            for (int i = 0; i < n; ++i) {
                if (lists[i] && lists[i]->val < smallest_value) {
                    smallest_value = lists[i]->val;
                    smallest_index = i;
                }
            }
            if (smallest_index == -1) break;
            candidate->next = lists[smallest_index];
            candidate = lists[smallest_index];
            lists[smallest_index] = lists[smallest_index]->next;
        }
        
        return dummyHead->next;
    }
};

下面这个代码写的较好。

https://algorithm.yuanbin.me/zh-hans/linked_list/merge_k_sorted_lists.html

  1. k个lists,两两合并
    参考https://zhuanlan.zhihu.com/p/56694331
    TBD

  2. k个lists,从底向上merge(分治法)
    参考https://zhuanlan.zhihu.com/p/56694331
    TBD

  3. 用最小堆。时间复杂度:假如总共有 N 个节点,每个节点入队出队都需要 log(k),所有时间复杂度是 O(N log(k))。
    代码如下:

/**
 * Definition of ListNode
 * class ListNode {
 * public:
 *     int val;
 *     ListNode *next;
 *     ListNode(int val) {
 *         this->val = val;
 *         this->next = NULL;
 *     }
 * }
 */
 
//bool operator > (const ListNode &a, const ListNode &b) { //最小堆
//    return a.val > b.val;
//}

class cmp {
public:
    bool operator() (ListNode* a, ListNode *b) {
        return a->val > b->val;
    }
};

class Solution {
public:
    /**
     * @param lists: a list of ListNode
     * @return: The head of one sorted list.
     */
    ListNode *mergeKLists(vector<ListNode *> &lists) {
       
        int listsSize = lists.size();
        if (listsSize == 0) return nullptr;
        
        ListNode dummy(0); 
        ListNode *head = &dummy; 
        
        //priority_queue<ListNode *, vector<ListNode *>, greater<ListNode *>> pq;
        priority_queue<ListNode *, vector<ListNode *>, cmp> pq;
    
        for (auto ptr : lists) {
            if (ptr) {
                pq.push(ptr);
            }
        }
        
        while(!pq.empty()) {
            ListNode *node = pq.top();
            cout<<"top.val="<<node->val<<endl;
            pq.pop();
            head->next = node;
            head = node;
            if (node->next) pq.push(node->next); //. has higher priority than *
        }
            
        return dummy.next;   
    }
};

二刷

struct cmp {
    bool operator()(ListNode *a, ListNode *b) {
        return a->val > b->val;
    }
};

class Solution {
public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        int nRow = lists.size();
        priority_queue<ListNode *, vector<ListNode *>, cmp> minHeap;
        ListNode *head = new ListNode();
        ListNode *origHead = head;
        for (int i = 0; i < nRow; i++) {
            if (lists[i]) {
                minHeap.push(lists[i]);
            }
        }
        while(!minHeap.empty()) {
            ListNode *topNode = minHeap.top();
            minHeap.pop();
            head->next = topNode;
            head = head->next;
            if (topNode->next) minHeap.push(topNode->next);
        }
        return origHead->next;
    }
};

三刷:注意decltype用法。

/**
 * Definition of ListNode
 * class ListNode {
 * public:
 *     int val;
 *     ListNode *next;
 *     ListNode(int val) {
 *         this->val = val;
 *         this->next = NULL;
 *     }
 * }
 */

class Solution {
public:
    /**
     * @param lists: a list of ListNode
     * @return: The head of one sorted list.
     */
    ListNode *mergeKLists(vector<ListNode *> &lists) {
        auto comp = [](ListNode *a, ListNode *b){ return a->val > b->val; };
        priority_queue<ListNode *, vector<ListNode *>, decltype(comp)> minHeap(comp);
        for (auto list : lists) {
            if (list) minHeap.push(list);
        }
        ListNode *dummy = new ListNode(0), *node = dummy;
        while (!minHeap.empty()) {
            auto topNode = minHeap.top();
            minHeap.pop();
            if (topNode) {
                node->next = new ListNode(topNode->val);
                node = node->next;
                if (topNode->next) minHeap.push(topNode->next);
            }
        }
        return dummy->next;
    }
};
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值