leetcode023:Merge k Sorted Lists

问题描述

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

问题分析

思路1

这个问题是leetcode021合并两个有序列表的增强版:合并k个有序列表。
实现原理比较相似:每次取k个列表表头结点,依次找出这些头结点最小的(排序,便于后续利用),然后取最小结点所在列表的下一结点。这次学习了如何利用sort()函数给vector的非基本类型ListNode排序。

  • 先写比较函数
bool cmp_by_ListNode(const ListNode *left, const ListNode *right){
     return left->val < right->val;
}
  • 调用sort()排序函数
sort(vecList.begin(), vecList.end(), cmp_by_ListNode);
  • 代码

待优化

bool cmp_by_ListNode(const ListNode *left, const ListNode *right){
     return left->val < right->val;
}

 class Solution {
 public:
     ListNode *mergeKLists(vector<ListNode *> &lists) {
         int size = lists.size();
         // ListNode *ans_final = NULL;
         ListNode *ans = NULL;
         ListNode *ans_p = NULL;
         vector<ListNode *> vecList;
         for (int i = 0; i < size; i++){
             if (lists[i]) { vecList.push_back(lists[i]); }
         }
         size = vecList.size();
         if (!size) return NULL;
         if (size == 1) return *(vecList.begin());
         sort(vecList.begin(), vecList.end(), cmp_by_ListNode);
         vector<ListNode *>::iterator it;
         ListNode *k = NULL;    //k结点的值来自于上次vecList表头值(即最小值所在结点)
         int val;
         int flag;              //0:表示k结点的值比vecList中任何结点值都小,此时直接将k结点加入ans列表中,并让k后续指向k->next
         while (vecList.size() > 1 || vecList.size() == 1 && k){
             it = vecList.begin();
             val = (*it)->val;
             flag = 1;
             if (k){
                 if (k->val <= val){
                     val = k->val;
                     flag = 0;
                 }
                 else{
                     //方案1,加入vecList再排序,复杂度O(n*logn),n为vecList结点数目,运行时间154 ms
                     /*vecList.push_back(k);
                     sort(vecList.begin(), vecList.end(), cmp_by_ListNode);*/
                     //因为vecList本身是有序的,所以无需排序,只要将k值插入合适位置即可使得vecList有序(减少计算量)
                     //方案2,直接插入,查找复杂度为O(n),插入复杂度也是O(n)[因为是连续内存,后面的元素需要腾出空间],运行时间65 ms
                     /*vector<ListNode *>::iterator loc;
                     for (loc = vecList.begin(); loc != vecList.end(); loc++){
                     if ((*loc)->val > k->val) break;
                     }
                     if (loc != vecList.end()){
                         vecList.insert(loc, k);
                     }
                     else{
                         vecList.push_back(k);
                     }*/
                     //方案2改进:使用二分法查找,运行时间:60 ms
                     int l = 0, r = vecList.size() - 1;
                     int mid =( l + r) / 2;
                     while (l<r){
                         if (k->val < vecList[mid]->val)
                             r = mid;
                         else
                             l = mid;
                         mid = (l + r) / 2;
                         if (mid == l) break;
                     }vector<ListNode *>::iterator loc;
                     if (k->val >= vecList[r]->val) vecList.push_back(k);
                     else if (r - l == 1 && k->val > vecList[l]->val){
                         loc = vecList.begin() + r;
                         vecList.insert(loc, k);
                     }
                     else{
                         loc = vecList.begin() + l;
                         vecList.insert(loc, k);
                     }
                 }
             }
             ListNode *node = new ListNode(val);
             if (!ans) ans_p = ans = node;
             else {
                 ans_p->next = node; ans_p = node;
             }
             if (flag){
                 k = (*it)->next;
                 vecList.erase(it);
             }
             else k = k->next;
         }
         //if (vecList.size() == 1 && (!k)){
             if (!ans) ans = *vecList.begin();
             else ans_p->next = *vecList.begin();
        // }
         return ans;
     }
 };
  • 优化后的代码
    上述思路每次取最小的思想归结为用最小堆,其建堆算法复杂度为O(n),且代码简化。基本和上述代码性能相当。
//运行时间:61 ms
bool cmp_by_ListNode(const ListNode *left, const ListNode *right){
     return left->val > right->val;
}
class Solution {
public:
    ListNode *mergeKLists(vector<ListNode *> &lists) {
        int size = lists.size();
        // ListNode *ans_final = NULL;
        ListNode *ans = NULL;
        ListNode *ans_p = NULL;
        vector<ListNode *> vecList;
        for (int i = 0; i < size; i++){
            if (lists[i]) { vecList.push_back(lists[i]); }
        }
        size = vecList.size();
        if (!size) return NULL;
        if (size == 1) return vecList[0];
        make_heap(vecList.begin(), vecList.end(), cmp_by_ListNode);
        ListNode *k = NULL; //k结点的值来自于上次vecList表头值(即最小值所在结点)
        int val;
        int flag;               //0:表示k结点的值比vecList中任何结点值都小,此时直接将k结点加入ans列表中,并让k后续指向k->next
        while (vecList.size() > 1 || vecList.size() == 1 && k){
            val = vecList.front()->val;
            flag = 1;
            if (k){
                if (k->val <= val){
                    val = k->val;
                    flag = 0;
                 }
                     else{
                         vecList.push_back(k);
                         push_heap(vecList.begin(), vecList.end(), cmp_by_ListNode);
                     }
                 }
                 ListNode *node = new ListNode(val);
                 if (!ans) ans_p = ans = node;
                 else {
                     ans_p->next = node; ans_p = node;
                 }
                 if (flag){
                     k = vecList.front()->next;
                     pop_heap(vecList.begin(), vecList.end(), cmp_by_ListNode);
                     vecList.pop_back();
                 }
                 else k = k->next;
             }
             //if (vecList.size() == 1 && (!k)){
                 if (!ans) ans = *vecList.begin();
                 else ans_p->next = *vecList.begin();
            // }
             return ans;
    }
};

思路2

直接把k个列表放一个列表里,然后快排或建最小堆,复杂度O(nlogn)
- 快排代码

//运行时间:43ms
bool cmp_by_ListNode(const ListNode *left, const ListNode *right){
     return left->val < right->val;
}
class Solution {
public:
    ListNode *mergeKLists(vector<ListNode *> &lists) {
        int size = lists.size();
        ListNode *ans = NULL;
        ListNode *ans_p = NULL;
        vector<ListNode *> vecList;
        for (int i = 0; i < size; i++){
            if (lists[i]) { vecList.push_back(lists[i]); }
        }
        size = vecList.size();
        if (!size) return NULL;
        if (size == 1) return vecList.front();
        int i = 0;
        while (i<size)
        {
            ListNode*p = vecList[i++];
            while (p->next){
                vecList.push_back(p->next);
                p = p->next;
            }
        }
        sort(vecList.begin(), vecList.end(), cmp_by_ListNode);
        size = vecList.size();
        i = 0;
        while (i<size){
            ListNode * node = new ListNode(vecList[i]->val);
            if (!ans) ans_p = ans = node;
            else { ans_p->next = node; ans_p = node; }
            i++;
        }
        return ans;
    }
};
  • 最小堆代码
    注:建立最小堆的比较函数是>,最大堆为<,STL默认建立最大堆。
//运行时间:52ms
bool cmp_by_ListNode(const ListNode *left, const ListNode *right){
     return left->val > right->val;
}
class Solution {
public:
    ListNode *mergeKLists(vector<ListNode *> &lists) {
        int size = lists.size();
        // ListNode *ans_final = NULL;
        ListNode *ans = NULL;
        ListNode *ans_p = NULL;
        vector<ListNode *> vecList;
        for (int i = 0; i < size; i++){
            if (lists[i]) { vecList.push_back(lists[i]); }
        }
        size = vecList.size();
        if (!size) return NULL;
        if (size == 1) return vecList[0];
        int i = 0;
        while (i<size)
        {
            ListNode*p = vecList[i++];
            while (p->next){
                vecList.push_back(p->next);
                p = p->next;
            }
        }
        make_heap(vecList.begin(), vecList.end(), cmp_by_ListNode);
        while (!vecList.empty()){
            if (!ans) ans_p = ans = vecList.front();
            else{ ans_p->next = vecList.front(); ans_p = vecList.front(); }
            pop_heap(vecList.begin(), vecList.end(), cmp_by_ListNode);
            vecList.pop_back();
        }
        if (ans_p) ans_p->next = NULL;
        // }
        return ans;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值