每日一道 LeetCode (7):合併兩個有序連結串列
每天 3 分鐘,走上演算法的逆襲之路。
前文合集
程式碼倉庫
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:又找到自己短板了,每天能通過這種方式發現一個短板補一個短板還是很開心的。