1. 程式人生 > 其它 >leetcode——合併K個升序連結串列

leetcode——合併K個升序連結串列

技術標籤:面試C++

目錄

題目:

示例:

提示:

方案一:暴力解法

方案二:順序合併

方案三:歸併

方案四:優先佇列


題目:

給定一個連結串列陣列,每個連結串列都已經按升序排列。請你將所有連結串列合併到一個升序連結串列中,返回合併後的連結串列。

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

示例:

輸入:lists = [[1,4,5],[1,3,4],[2,6]]
輸出:[1,1,2,3,4,4,5,6]
解釋:連結串列陣列如下:
[
  1->4->5,
  1->3->4,
  2->6
]
將它們合併到一個有序連結串列中得到。
1->1->2->3->4->4->5->6

提示:

  • k == lists.length
  • 0 <= k <= 10^4
  • 0 <= lists[i].length <= 500
  • -10^4 <= lists[i][j] <= 10^4
  • lists[i] 按 升序 排列
  • lists[i].length 的總和不超過 10^4

方案一:暴力解法

/**
 * 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) {}
 * };
 */
class Solution {
public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        ListNode* head = nullptr;
        ListNode* cur = nullptr;
        while(true) {
            int index = -1;
            for (int i = 0; i < lists.size(); i++) {
                if (lists[i] == nullptr) {
                    continue;
                }
                if (index < 0 || lists[index]->val > lists[i]->val) {
                    index = i;
                }
            }
            if (index < 0) {
                return head;
            }
            if (head == nullptr) {
                head = cur = lists[index];
            }else {
                cur->next = lists[index];
                cur = cur->next;
            }
            lists[index] = lists[index]->next;
        }
        return head;
    }
};

時間複雜度O(k^2n)

空間複雜度O(1)

方案二:順序合併

/**
 * 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) {}
 * };
 */
class Solution {
private:
/*
合併兩個陣列,時間複雜度O(n),空間複雜度O(1)
*/
ListNode* mergeTwoList(ListNode* l1, ListNode* l2) {
    if (!l1 || !l2) return !l1 ? l2 : l1;
    ListNode head, *cur = &head;

    while (l1 && l2) {
        if (l1->val < l2->val) {
            cur->next = l1;
            l1 = l1->next;
        } else {
            cur->next = l2;
            l2 = l2->next;
        }
        cur = cur->next;
    }
    cur->next = l1 ? l1 : l2;
    return head.next;
}
public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        ListNode* head = nullptr;
        ListNode* cur = nullptr;
        for (int i = 0; i < lists.size(); i++) {
            head = mergeTwoList(head, lists[i]);
        }
        return head;
    }
};

時間複雜度:O(k^2n)

空間複雜度:O(1)

方案三:歸併

/**
 * 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) {}
 * };
 */
class Solution {
private:
/*
合併兩個陣列,時間複雜度O(n),空間複雜度O(1)
*/
ListNode* mergeTwoList(ListNode* l1, ListNode* l2) {
    if (!l1 || !l2) return !l1 ? l2 : l1;
    ListNode head, *cur = &head;

    while (l1 && l2) {
        if (l1->val < l2->val) {
            cur->next = l1;
            l1 = l1->next;
        } else {
            cur->next = l2;
            l2 = l2->next;
        }
        cur = cur->next;
    }
    cur->next = l1 ? l1 : l2;
    return head.next;
}

ListNode* merge(vector<ListNode*>& lists, int l, int r) {
    if (l == r) return lists[l];
    if (l > r) return nullptr;
    int mid = (l + r) >> 1;
    return mergeTwoList(merge(lists, l, mid), merge(lists, mid + 1, r));
}
public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        return merge(lists, 0, lists.size() - 1);
    }
};

時間複雜度O(k*log^k*n)

空間複雜度O(log^k)

方案四:優先佇列

https://blog.csdn.net/weixin_36888577/article/details/79937886優先佇列相關知識

/**
 * 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) {}
 * };
 */
class Solution {
public:
    struct Status {
        int val;
        ListNode* ptr;
        bool operator < (const Status &rhs) const {
            return rhs.val < val;
        }
    };
    priority_queue <Status> q;
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        for (auto node : lists) {
            if (node != nullptr) {
                q.push({node->val, node});
            }
        }
        ListNode head, *cur = &head;
        while(!q.empty()) {
            Status s = q.top();
            q.pop();
            cur->next = s.ptr;
            cur = cur->next;
            if (s.ptr->next) {
                q.push({s.ptr->next->val, s.ptr->next});
            }
        }
        return head.next;
    }
};

時間複雜度O(k*log^k*n)

空間複雜度O(k)