天天看點

Leetcode 23. Merge k Sorted ListsLeetcode 23. Merge k Sorted Lists

  • Leetcode 23. Merge k Sorted Lists
    • 題目
    • 題目解析
    • 代碼
    • 連結清單類題目總結

Leetcode 23. Merge k Sorted Lists

題目

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

Example:

Input:
[
  ->->,
  ->->,
  ->
]
Output: ->->->->->->->
           

題目解析

題目的意思很簡單,合并多個排序的連結清單,看起來和歸并排序非常相似,可以說基本相同的。按照正常的思路,設立一個連結清單頭,然後依次比較這

k

個連結清單中較小的一個,挂在這個連結清單頭上。很快就寫出代碼,但果然,肯定是逾時的,

hard

的應該沒這麼簡單==

分析一下,時間主要花在每次擴充時對這些連結清單頭進行周遊,如果加快搜尋呢,當然是進行排序。我們需要維護的是一個已經排序的結構,每次能夠迅速找到最小值,可以選擇的是排序的二叉樹,堆等。考慮到STL中實作的

set

map

這些都是排序的結構,是以直接應用即可。

接下來就是程式設計的問題了,我們需要的是把節點放入到

set

中,但如何重定義他的比較函數呢,因為重載運算符必須是對象,不能直接對指針重載運算符,是以我們用一個

pair

結構,結構的第一個元素是連結清單節點,第二個參數是連結清單的值,然後重載運算符就可以了。由于可能會有重複值,是以需要用有重複值的

set

代碼

經過上面的分析,代碼如下:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
// 定義結構并重載運算符
using PointX = pair<ListNode *, int>;
bool operator<(const PointX &a, const PointX &b)
{
    return a.second < b.second;
}

class Solution {
public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        multiset<PointX, less<PointX>> mpset;
        for (auto i : lists)
            if(i)   // 對應于[[]]的測試用力
                mpset.insert(make_pair(i,i->val));
        ListNode * tmp = nullptr;
        ListNode * head = nullptr;
        while (!mpset.empty())
        {
            auto it = mpset.begin();
            if (tmp == nullptr) // 确定表頭,head記錄表頭
            {
                tmp = it->first;
                head = tmp;
            }
            else
            {
                tmp->next = it->first;
                tmp = tmp->next;
            }
            auto ptr = it->first;
            mpset.erase(it);    // 删除節點,注意是删除疊代器,不然重複值可能會全部删除了
            if (ptr->next)
            {
                mpset.insert(make_pair(ptr->next, ptr->next->val));
            }
        }
        if(tmp)     // 特殊情況判斷
            tmp->next = nullptr;
        return head;
    }
};
           

連結清單類題目總結

最近準備秋招,做了一些連結清單類的題目,總體感覺連結清單類題目容易出錯,需要考慮一些特殊的情況,總結如下:

1. 獲得

->next

->val

前,需要判斷節點是否為空

2. 可以增加一個頭節點,減少頭節點是否為空的判斷,傳回的時候傳回

nhead->next

就可以

3. 判斷題目需求連結清單分成幾段,記錄每一段的開頭和結尾,先在紙上畫出圖,确定要使用幾個指針來記錄

4. 判斷輸入節點是否為空

5. 注意尾巴指針置空,否則會無限循環