// SPDX-License-Identifier: Apache-2.0
// Copyright 2025 MergeKSortedLists Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef MERGE_K_SORTED_LISTS_H
#define MERGE_K_SORTED_LISTS_H

#include <vector>
#include <queue>

/** Definition for singly-linked list node. */
struct ListNode {
    int mVal;
    ListNode* mpNext;
    
    /** Default constructor. */
    ListNode() : mVal(0), mpNext(nullptr) {}
    
    /** Constructor with value.
     * @param val The value to store in the node
     */
    ListNode(int val) : mVal(val), mpNext(nullptr) {}
    
    /** Constructor with value and next pointer.
     * @param val The value to store in the node
     * @param next Pointer to the next node
     */
    ListNode(int val, ListNode* next) : mVal(val), mpNext(next) {}
};

/** Merge K Sorted Lists solver class.
 *
 * This class provides multiple approaches to merge k sorted linked lists
 * into one sorted linked list efficiently.
 */
class MergeKSortedLists {
public:
    /** Default constructor. */
    MergeKSortedLists();
    
    /** Virtual destructor. */
    virtual ~MergeKSortedLists();
    
    // OPERATIONS
    
    /** Merge k sorted linked lists using divide and conquer approach.
     *
     * Time Complexity: O(N log k) where N is total number of nodes
     * Space Complexity: O(log k) for recursion stack
     *
     * @param lists Vector of pointers to the head of k sorted linked lists
     * @return Pointer to the head of the merged sorted linked list
     */
    ListNode* MergeKListsDivideConquer(std::vector<ListNode*>& lists);
    
    /** Merge k sorted linked lists using priority queue (min-heap).
     *
     * Time Complexity: O(N log k) where N is total number of nodes
     * Space Complexity: O(k) for the priority queue
     *
     * @param lists Vector of pointers to the head of k sorted linked lists
     * @return Pointer to the head of the merged sorted linked list
     */
    ListNode* MergeKListsPriorityQueue(std::vector<ListNode*>& lists);
    
    /** Merge k sorted linked lists by merging one by one.
     *
     * Time Complexity: O(k*N) where N is total number of nodes
     * Space Complexity: O(1)
     *
     * @param lists Vector of pointers to the head of k sorted linked lists
     * @return Pointer to the head of the merged sorted linked list
     */
    ListNode* MergeKListsOneByOne(std::vector<ListNode*>& lists);

private:
    // OPERATIONS
    
    /** Merge two sorted linked lists.
     *
     * @param list1 Pointer to the head of first sorted linked list
     * @param list2 Pointer to the head of second sorted linked list
     * @return Pointer to the head of the merged sorted linked list
     */
    ListNode* MergeTwoLists(ListNode* list1, ListNode* list2);
    
    /** Merge lists in a range using divide and conquer.
     *
     * @param lists Vector of pointers to the head of k sorted linked lists
     * @param start Start index of the range
     * @param end End index of the range
     * @return Pointer to the head of the merged sorted linked list
     */
    ListNode* MergeRange(std::vector<ListNode*>& lists, int start, int end);
};

/** Comparator for priority queue to maintain min-heap property. */
struct ListNodeComparator {
    /** Compare two ListNode pointers.
     *
     * @param a First ListNode pointer
     * @param b Second ListNode pointer
     * @return true if a->mVal > b->mVal (for min-heap)
     */
    bool operator()(ListNode* a, ListNode* b) {
        return a->mVal > b->mVal;
    }
};

// UTILITY FUNCTIONS

/** Create a linked list from vector of values.
 *
 * @param values Vector of integer values
 * @return Pointer to the head of the created linked list
 */
ListNode* CreateList(const std::vector<int>& values);

/** Print a linked list.
 *
 * @param head Pointer to the head of the linked list
 */
void PrintList(ListNode* head);

/** Delete a linked list and free memory.
 *
 * @param head Pointer to the head of the linked list
 */
void DeleteList(ListNode* head);

#endif // MERGE_K_SORTED_LISTS_H