leetcode-個人題解23
阿新 • • 發佈:2019-02-16
LEETCODE專題
23. Merge k Sorted Lists
題目要求:
題目意思很簡單,就是給定許多條有序連結串列,然後讓我們合併成一條有序連結串列再返回即可。
下面簡要介紹一下2種思路:
第一種就是比較暴力的方法:在所有的連結串列中取一個最小的數,然後將對應的連結串列結點指標往後移一位,同時新建一個連結串列結點;此後重複所有步驟,只是新建的連結串列結點要和之前的連結串列結點相連,其實也就是一個next指標的的問題。
當然在這個過程中要注意2點:1.注意結束條件是所有連結串列都已經走完;2.要判斷下連結串列是否已經走完,才能決定比不比較該連結串列結點的值- 這種方法雖然思路簡單些,但是實現起來其實非常的繁瑣,不僅每次都要比較k - 1次,而且還要注意很多判斷條件,以防記憶體訪問錯誤(比如訪問NULL)。而且每一次比較都要掃描k次,假設一共有n個結點的話,就需要掃描n次,時間複雜度就成了O(nk)了。
第二種方法就是歸併排序,做過leetcode第21題的話就會發現,21題簡直就是為23題量身訂製的介面!
將k個連結串列分成k / 2份,每2個連結串列進行一次歸併,這樣就會得到k / 2個新連結串列。重複上述過程,連結串列數目會呈現這樣的變化規律:k -> k / 2 -> k / 4 -> … -> 1,最後只存在1條連結串列就可以返回該連結串列了。其中每一趟都掃描所有連結串列1次。- 這種方法思路簡單,而且最主要的是可以充分利用已有資源。假設一共有n個結點,那時間複雜度就是O(n logk)了。
下面直接上code:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* merge2Lists(ListNode* l1, ListNode* l2) {
int min;
// get the smaller value of the two value
if (l1 == NULL && l2 == NULL) {
return NULL;
} else if (l2 == NULL || (l1 != NULL &&
l1->val < l2->val) ) {
min = l1->val;
l1 = l1->next;
} else {
min = l2->val;
l2 = l2->next;
}
ListNode * newListNode = new ListNode(min);
ListNode * newhead = newListNode;
while (l1 != NULL || l2 != NULL) {
if (l2 == NULL || (l1 != NULL &&
l1->val < l2->val)) {
min = l1->val;
l1 = l1->next;
} else {
min = l2->val;
l2 = l2->next;
}
newListNode->next = new ListNode(min);
newListNode = newListNode->next;
}
return newhead;
}
/* merge 2 lists to produce a list twice as large
* as the former list. Each pass will take
* O(n). Totally, it has logk passes and thus its
* time complexity is O(nlogk).
*/
ListNode* mergeKLists(vector<ListNode*>& lists) {
if (lists.size() == 0) {
return NULL;
}
ListNode * l1, * l2;
while (lists.size() > 1) {
l1 = lists.back();
lists.pop_back();
l2 = lists.back();
lists.pop_back();
lists.insert(lists.begin(), merge2Lists(l1, l2) );
}
return lists[0];
}
};
時間複雜度:O(n logk)