[劍指-Offer] 25. 合併兩個排序的鏈表(遞歸、迭代、常規解法)

1. 題目來源

鏈接:合併兩個排序的鏈表
來源:LeetCode——《劍指-Offer》專項

2. 題目說明

輸入兩個遞增排序的鏈表,合併這兩個鏈表並使新鏈表中的節點仍然是遞增排序的。

示例1:

輸入:1->2->4, 1->3->4
輸出:1->1->2->3->4->4

限制:

  • 0 <= 鏈表長度 <= 1000

3. 題目解析

方法一:遞歸解法

肯定是優雅的遞歸解法最得人心啊,合併兩個排序鏈表與合併兩個排序數組沒什麼區別的。如果兩個鏈表的頭結點有其中一個爲 nullptr,那就返回另一個即可。這裏包含了原本鏈表就爲空鏈表以及其中一個鏈表合併完畢,這兩種情況。然後就依據大小關係遞歸插入就行了。

參見代碼如下:

// 執行用時 :24 ms, 在所有 C++ 提交中擊敗了47.33%的用戶
// 內存消耗 :20.3 MB, 在所有 C++ 提交中擊敗了100.00%的用戶

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        if (l1 == nullptr) return l2;
        if (l2 == nullptr) return l1;
        
        ListNode* tmp = nullptr;
        if (l1->val < l2->val) {
            tmp = l1;
            tmp->next = mergeTwoLists(l1->next, l2);
        }
        else {
            tmp = l2;
            tmp->next = mergeTwoLists(l1, l2->next);
        }
        return tmp;
    }
};

方法二:迭代解法

目的是將兩個有序鏈表合併成一個有序鏈表,因此每次操作都是獲取 l1 指向的結點和 l2 指向的結點中,值較小的結點。迭代和遞歸都是如此。使用迭代的時,爲了將第一個結點與其餘結點統一處理,一般會定義一個頭結點。主要步驟如下:

  • 定義頭結點
  • l1 < l2,則將 l1 鏈接到頭結點的 next 位置
  • 否則將 l2 鏈接到頭結點的 next 位置
  • 循環進行,直至 l1l2NULL
  • 最後,將 l1l2 中剩下的部分,鏈接到頭結點後面

參見代碼如下:

// 執行用時 :40 ms, 在所有 C++ 提交中擊敗了6.05%的用戶
// 內存消耗 :19.9 MB, 在所有 C++ 提交中擊敗了100.00%的用戶

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        if (l1 == nullptr) return l2;
        if (l2 == nullptr) return l1;

        ListNode* head = new ListNode(0);
        ListNode* ret = head;
        while (l1 && l2) {
            if (l1->val < l2->val) {
                head->next = l1;
                l1 = l1->next;
                head = head->next;
            }
            else {
                head->next = l2;
                l2 = l2->next;
                head = head->next;
            } 
        }
        head->next = l1 == nullptr ? l2 : l1;
        return ret->next;
    }
};


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章