牛客網刷題-合併k個已排序的連結串列
阿新 • • 發佈:2021-02-01
問題描述
合併 k 個已排序的連結串列並將其作為一個已排序的連結串列返回。分析並描述其複雜度。
輸入描述:
輸入一個連結串列的集合
輸出描述:
輸出合併後的連結串列
示例
示例1
輸入
[{1,2,3},{4,5,6,7}]
輸出
{1,2,3,4,5,6,7}
解決思路
分析
- 通過順序合併的方式,先合併前兩個連結串列,然後以合併後的連結串列一次與後面每一個連結串列合併(這種方式會花費額外的時間,這裡不做介紹)
- 通過二分分組的方式,對連結串列分組,分 k/2 組,對每組的兩個連結串列進行合併,取合併後的連結串列再進行分組,重複這個過程
- 通過優先佇列的方式,通過維護每個連結串列的首元素,依次彈出追加元素(後期會補充程式碼)
方法
- 通過對連結串列進行二分分組的方式實現排序
程式碼實現
// 思路1
public class Solution {
public ListNode merge(ArrayList<ListNode> lists, int l, int r) {
if (l == r) {
return lists.get(l);
}
if (l > r) {
return null;
}
int mid = (l + r) >> 1;
return mergeTwoLists(merge(lists, l, mid), merge(lists, mid + 1, r));
}
private ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if (l1 == null || l2 == null) {
return l1 == null ? l2 : l1;
}
ListNode dummy = new ListNode(0);
ListNode temp = dummy;
while (l1 != null && l2 != null) {
if (l1.val < l2.val) {
temp.next = l1;
l1 = l1.next;
} else {
temp.next = l2;
l2 = l2.next;
}
temp = temp.next;
}
if (l1 != null) temp.next = l1;
if (l2 != null) temp.next = l2;
return dummy.next;
}
}
時間複雜度分析:
第一次分組:k/2個組,每組合並需要的時間複雜度為2個連結串列的長度和,假設最長為n,則每組合並的時間複雜度為O(2n),總的時間複雜度為:O(k/2 * 2n) = O(kn)
第二次分組:k/4個組,每組合並需要的時間複雜度為4個連結串列的長度和 O(4n) 【注意:這裡承接了第一組,所以長度會*2】,總的時間複雜度為:O(k/4 * 4n) = O(kn)
第logk次分割槽,相同,因為採用了二分的方法分組,所以k組分組的總共次數為logk次,所以總的時間複雜度為O(logk * kn)
空間複雜度分析:
因為採用遞迴的方式,沒有申請額外的空間儲存,所以空間複雜度為O(1)
小夥伴如果想測試的話,可以直接到牛客網這個連結做測試