1. 程式人生 > 其它 >牛客網刷題-合併k個已排序的連結串列

牛客網刷題-合併k個已排序的連結串列

技術標籤:演算法Java演算法面試

問題描述

合併 k 個已排序的連結串列並將其作為一個已排序的連結串列返回。分析並描述其複雜度。

輸入描述:
輸入一個連結串列的集合

輸出描述:
輸出合併後的連結串列

示例

示例1

輸入
[{1,2,3},{4,5,6,7}]

輸出
{1,2,3,4,5,6,7}

解決思路

分析

  1. 通過順序合併的方式,先合併前兩個連結串列,然後以合併後的連結串列一次與後面每一個連結串列合併(這種方式會花費額外的時間,這裡不做介紹)
  2. 通過二分分組的方式,對連結串列分組,分 k/2 組,對每組的兩個連結串列進行合併,取合併後的連結串列再進行分組,重複這個過程
  3. 通過優先佇列的方式,通過維護每個連結串列的首元素,依次彈出追加元素(後期會補充程式碼)

方法

  1. 通過對連結串列進行二分分組的方式實現排序

程式碼實現

// 思路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)

小夥伴如果想測試的話,可以直接到牛客網這個連結做測試

合併k個已排序的連結串列-牛客網