1. 程式人生 > 實用技巧 >每日一道 LeetCode (7):合併兩個有序連結串列

每日一道 LeetCode (7):合併兩個有序連結串列

每天 3 分鐘,走上演算法的逆襲之路。

前文合集

每日一道 LeetCode 前文合集

程式碼倉庫

GitHub: https://github.com/meteor1993/LeetCode

Gitee: https://gitee.com/inwsy/LeetCode

題目:合併兩個有序連結串列

題目來源:https://leetcode-cn.com/problems/merge-two-sorted-lists/

將兩個升序連結串列合併為一個新的 升序 連結串列並返回。新連結串列是通過拼接給定的兩個連結串列的所有節點組成的。

示例:

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

解題方案:迭代

首先需要了解一下連結串列的資料結構,如果這個不清楚這道題完全沒得玩。

我還是先寫下定義連結串列的程式碼,配合程式碼好理解一下:

public class ListNode {

    public int val;
    public ListNode next;

    public ListNode() {

    }

    public ListNode(int val) {
        this.val = val;
    }

    public ListNode (int val, ListNode next) {
        this.val = val;
        this.next = next;
    }
}

這段程式碼異常簡單,定義了一個數據域用來存放一個整數 val ,然後定義了一個指標指向另一個 ListNode ,這就形成了一個單獨的連結串列上的節點。

接下來是排序,我相信如果是兩個陣列排序大多數人應該都寫的出來,實際上鍊表的排序和陣列的排序也差不多,正向思維就是直接迴圈排序,簡單粗暴。

思路簡單程式碼也簡單,看下我寫的單純的迭代排序的程式碼:

// 暴力迭代
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
    ListNode prehead = new ListNode(-1);

    ListNode prev = prehead;

    while (l1 != null && l2 != null) {
        if (l1.val < l2.val) {
            prev.next = l1;
            l1 = l1.next;
        } else {
            prev.next = l2;
            l2 = l2.next;
        }
        prev = prev.next;
    }

    prev.next = l1 == null ? l2 : l1;

    return prehead.next;
}

是不是很簡單,判斷兩個連結串列節點的大小,然後修改指標的指向,接著迴圈,迴圈到兩個節點都為 null 為止。

需要注意的是當迴圈終止的時候, l1 和 l2 最多有一個是非空的,這時候需要在

解題思路:遞迴

秉承著良好的習慣,做完題以後看下答案,大體排序思路沒什麼滑頭,但是看到了另一種寫法,這個寫法寫起來說實話,還真有點不大會寫。

雖然這麼說有點丟人,但我就是這麼不要臉,就這麼直接說出來了,遞迴這種方式,平時基本不怎麼寫,突然冷不丁的讓我寫一下,還是蠻困難的。

// 遞迴
public ListNode mergeTwoLists_1(ListNode l1, ListNode l2) {
    if (l1 == null) return l2;
    else if (l2 == null) return l1;
    else if (l1.val < l2.val) {
        l1.next = mergeTwoLists(l1.next, l2);
        return l1;
    } else {
        l2.next = mergeTwoLists(l1, l2.next);
        return l2;
    }
}

遞迴的程式碼看起來是十分簡潔的,簡潔的代價是可讀性降低。

不過話說回來,遞迴的寫法是每一位碼農都應該熟悉的,雖然不常用。。。

PS:又找到自己短板了,每天能通過這種方式發現一個短板補一個短板還是很開心的。