23. Merge k Sorted Lists

題干

Merge k Sorted Lists
Difficulty: Hard
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.

合并K個已經排序的數組。

解題思路:

難度感覺算不上Hard(畢竟我做不出來的都是Hard),不過為了方便調試這次用了.net來寫。
拿到題目最開始的反應是對于數組中的每一個鏈表都定義一個指針,每次遍歷所有的指針,記錄最小的值以及出現的位置,遍歷完成后將最小值插入結果鏈表中,如果遍歷后發現每一個指針都指向空節點則說明遍歷完成。
最后成品:

        public ListNode MergeKLists(ListNode[] lists)
        {
            ListNode head = null, cursor = null;
            while (true)
            {
                var indexs = new List<int>();
                var min = int.MaxValue;
                for (var i = 0; i < lists.Length; i++)
                {
                    if (lists[i] == null)
                    {
                        continue;
                    }
                    if (lists[i].val > min)
                    {
                        continue;
                    }
                    else
                    {
                        if (lists[i].val < min)
                        {
                            indexs.Clear();
                            min = lists[i].val;
                        }
                        indexs.Add(i);
                    }
                }
                if (min == int.MaxValue)
                {
                    break;
                }
                else
                {
                    for (var i = 0; i < indexs.Count; i++)
                    {
                        if (head == null)
                        {
                            head = new ListNode(min);
                            cursor = head;
                        }
                        else
                        {
                            cursor.next = new ListNode(min);
                            cursor = cursor.next;
                        }
                        lists[indexs[i]] = lists[indexs[i]].next;
                    }
                }
            }
            return head;
        }

Runtime: 112 ms 91.21%
時間復雜度O(K*log(N))
K是鏈表數組的長度,N是節點數量。
Memory Usage: 28.8 MB 8.33%
空間復雜度O(K+N)
其中O(N)指的是最后長度為N的排序后數組。
O(K)則是我為了存儲指針位置而新建的List。
時間上我很滿意了,但是空間復雜度看上去很高,試著去減少一下。
結果鏈表的空間肯定是不能省的,那么只能省去List了,每次只push一個最小值進去,只記錄最小值以及最小值的位置

        public ListNode MergeKLists(ListNode[] lists)
        {
            ListNode head = null, cursor = null;
            while (true)
            {
                var index = -1;
                var min = int.MaxValue;
                for (var i = 0; i < lists.Length; i++)
                {
                    if (lists[i] == null)
                    {
                        continue;
                    }
                    if (lists[i].val >= min)
                    {
                        continue;
                    }
                    else
                    {
                        min = lists[i].val;
                        index = i;
                    }
                }
                if (index == -1)
                {
                    break;
                }
                else
                {

                    if (head == null)
                    {
                        head = new ListNode(min);
                        cursor = head;
                    }
                    else
                    {
                        cursor.next = new ListNode(min);
                        cursor = cursor.next;
                    }
                    lists[index] = lists[index].next;
                }
            }

            return head;
        }

Runtime: 584 ms
Memory Usage: 29.3 MB
這樣做肯定增加時間的,時間復雜度應該為(O(KN)),但是空間復雜度應該能縮減為O(N)。
但是結果讓我大跌眼鏡,空間占用不減反增,這里是實在不能理解。

其余解法

回去翻看LeetCode上的solution,他列出了五種解法。
最簡單的應該就是暴力求解了,將所有的鏈表中的節點都push到一個數組中,排序后生成新的鏈表。
時間O(N*log(N)),空間O(N)。

另一個Smart Play則是將問題簡化為(K-1)次合并兩個排序數組,我個人覺得思路比我的好,很多復雜問題都能簡化為多個簡單問題的累加。時間復雜度O(KN),空間復雜度O(1)。

最后一種解法則是上一個方法的改進,每次合并floor(k/2)個數組,這樣合并次數就被減少到ceil(log2(k))次了。這樣就減少了數組中大部分鏈表的結點需要排序的次數,而后幾個鏈表的元素排序次數則會略有增加,大部分情況下優于上面的解。除非最后一個鏈表節點特別多,其余鏈表節點特別少,這樣的話上一個做法會優于這個。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容