023 Merge k Sorted Lists [Leetcode]

題目內容:

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

題目分析:
k個排過序的鏈表,要將它們合併起來就要求能夠在較短的時間內將當前的k個數進行排序,並且能夠高效得支持數字的增刪操作。
可以使用的方法有:敗者樹,堆排序,這兩個算法在插入、刪除節點的時候複雜度都爲O(n)。

處理流程:
1. 使用每個鏈表起始的節點,共k個節點,進行堆排序,複雜度O(klogk)
2. 之後從這k個節點中選擇一個最大的,插入到新的鏈表中去。
3. 被選中的那個鏈表的節點的下一個節點如果存在,插入到堆中去。
4. 回到步驟2

結束條件爲堆中元素少於等於1個,即只有最後一個鏈表或沒有鏈表剩餘。

使用堆的代碼:
需要注意的是,priority_queue默認實現的是最大堆,而stl中的比較函數默認是通過“< ”符號來實現,因此實現最小堆的時候要重寫比較函數,將<重寫爲>。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */

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

class Solution {
public:
    ListNode *mergeKLists(vector<ListNode *> &lists) {
        priority_queue<ListNode *, vector<ListNode *>, cmp> min_heap;

        for(int i = 0; i < lists.size(); ++i) {
            if(lists[i] != NULL)
                min_heap.push(lists[i]);
        }

        ListNode *pre_head(new ListNode(0)), *curr(pre_head);
        while(min_heap.size() > 1) {
            curr->next = min_heap.top();
            min_heap.pop();
            curr = curr->next;
            if(curr->next != NULL)
                min_heap.push(curr->next);
        }

        if(min_heap.size() == 1) {
            curr->next = min_heap.top();
            min_heap.pop();
        }

        ListNode *head = pre_head->next;
        pre_head->next = NULL;
        delete pre_head;

        return head;
    }
};

使用敗者樹的代碼:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *mergeKLists(vector<ListNode *> &lists) {
        int size = lists.size();
        if (size == 0)
            return NULL;
        int *key = new int[size + 1];
        key[size] = INT_MIN;
        ListNode **elements = new ListNode*[size];

        int *loser = new int[size];
        for (int i = 0; i < size; i++) {
            elements[i] = lists[i];
            loser[i] = size;
            if (elements[i] != NULL)
                key[i] = elements[i]->val;
            else key[i] = INT_MAX;
        }
        for (int i = 0; i < size; i++) {
            adjust(loser, key, i, size);
        }

        ListNode *head = NULL, *curr = NULL;
        while (true) {
            if (key[loser[0]] == INT_MAX) {
                break;
                curr->next = NULL;
            }
            if (head == NULL) {
                head = elements[loser[0]];
                curr = elements[loser[0]];
                elements[loser[0]] = elements[loser[0]]->next;
            }
            else {
                curr->next = elements[loser[0]];
                curr = curr->next;
                elements[loser[0]] = elements[loser[0]]->next;
            }
            if(elements[loser[0]] != NULL)
                key[loser[0]] = elements[loser[0]]->val;
            else 
                key[loser[0]] = INT_MAX;
            adjust(loser, key, loser[0], size);
        }
        return head;
    }

    void adjust(int loser[], int key[], int k, int size) {
        for (int i = (size + k)/2; i > 0; i /= 2) {
            if (key[loser[i]] < key[k]) {
                int temp = k;
                k = loser[i];
                loser[i] = temp;
            }
        }
        loser[0] = k;
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章