Leetcode – Merge k sorted lists

https://leetcode.com/problems/merge-k-sorted-lists/

ListNode* merge(ListNode* l1, ListNode* l2) {
    ListNode dummy;
    auto tail = &dummy;
    while (l1 && l2) {
        if (l1->val <= l2->val) {
            tail->next = l1;
            l1 = l1->next;
            
        } else {
            tail->next = l2;
            l2 = l2->next;
        }
        tail = tail->next;
    }
    
    tail->next = l1 ? l1 : l2;
    
    return dummy.next;
}

ListNode* merge_div_conq(std::vector<ListNode*>& lists) {
    // could be optimized by taking two lists at a time instead
    // of merging at end always
    while (lists.size() > 1) {
        auto merged = merge(lists[lists.size() - 1], lists[lists.size() - 2]);
        lists.pop_back();
        lists.pop_back();
        lists.emplace_back(merged);
    }
    return lists.empty() ? nullptr : lists.front();
}


class Solution {
public:
    #ifdef false
    // divide-and-conquer (slower than min-heap)
    ListNode* mergeKLists(vector<ListNode*>& lists) { 
        return merge_div_conq(lists);
    }
    #endif
    
    // solution with min-heap
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        auto compare =[](const ListNode* lhs, const ListNode* rhs) {
            return lhs->val > rhs->val;
        };
        
        using PriorityQueue = std::priority_queue<ListNode*,std::vector<ListNode*>,decltype(compare)>;
        PriorityQueue pq(compare);
        for (auto& l : lists) {
            if (l)
                pq.push(l);
        }
        
        ListNode dummy;
        auto tail = &dummy;
        while (!pq.empty()) {
            auto node = pq.top();
            pq.pop();
            
            if (node->next) {
                pq.push(node->next);
            }
            
            tail->next = node;
            tail = tail->next;
        }
        
        return dummy.next;
    }
};