002.单链表的归并

/**
 * 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) {}
 * };
 */

1.二路归并

(1)采用递归的解法,只要比较list1和list2当前节点的值,再递归的求解后面的链表即可

class Solution {
public:
    ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
        if(list1 == nullptr) return list2;
        else if(list2 == nullptr) return list1;
        else if(list1->val <= list2->val){
            list1->next = mergeTwoLists(list1->next,list2);
            return list1;
        }else{
            list2->next = mergeTwoLists(list1,list2->next);
            return list2;
        }
    }
};

时间复杂度:\(O(n+m)\)
(2)采用非递归解法,和递归操作同理,只是把搜索的过程用p来代替

lass Solution {
public:
    ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
        ListNode* res = new ListNode();
        ListNode* p = res;
        while(list1 != nullptr && list2 != nullptr)
        {
            if(list1->val < list2->val)
            {
                p->next = list1;
                list1 = list1->next;
            }
            else
            {
                p->next = list2;
                list2 = list2->next;
            }
            p = p->next;
        }
        
        p->next = list1 == nullptr ? list2 : list1;

        return res->next;
    }
};

时间复杂度:\(O(n+m)\)
说明:p=p->next和递归的操作相对应

2.多路归并
(1)采用分治算法,两两合并

class Solution {
    ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
            ListNode* res = new ListNode();
            ListNode* p = res;
            while(list1 != nullptr && list2 != nullptr)
            {
                if(list1->val < list2->val)
                {
                    p->next = list1;
                    list1 = list1->next;
                }
                else
                {
                    p->next = list2;
                    list2 = list2->next;
                }
                p = p->next;
            }
            
            p->next = list1 == nullptr ? list2 : list1;

            return res->next;
    }

    ListNode* mergeRange(vector<ListNode*>& lists, int i, int j) {
        if (i > j) return nullptr;
        if (i == j) return lists[i]; 
        
        int mid = i+j>>1; 
        ListNode* left = mergeRange(lists, i, mid);
        ListNode* right = mergeRange(lists, mid+1, j);
        
        return mergeTwoLists(left, right);
    }



public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        return  mergeRange(lists, 0, lists.size()-1);
    }
};

时间复杂度:\(O(n \log m)\)

(2)采用优先队列,每次弹出最小节点,同时压入最小节点的下一个节点

class Solution {
public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        auto cmp = [](ListNode* a, ListNode* b) {
            return a->val > b->val; 
        };
        
        priority_queue<ListNode*, vector<ListNode*>, decltype(cmp)> q(cmp);

        for (auto head : lists)
            if (head != nullptr)
                q.push(head);
        
        ListNode dummy(0);
        ListNode* p = &dummy;
        
        while (!q.empty()) {
            ListNode* cur = q.top();
            q.pop();
            if (cur->next != nullptr)
                q.push(cur->next);
            p->next = cur;
            p = p->next;
        }
        
        p->next = nullptr; 
        return dummy.next;
    }
};

时间复杂度\(O(n\log m)\)

posted @ 2025-06-02 13:44  _P_D_X  阅读(19)  评论(0)    收藏  举报