劍指offer之合併兩個排序的列表
阿新 • • 發佈:2018-12-01
合併兩個排序的列表
歡迎關注作者部落格
簡書傳送門
題目
輸入兩個遞增排序的連結串列,合併這兩個連結串列並使新連結串列中的結點仍然是按照遞增排序的,並返回合併後的頭結點。
思路
假如List1中的頭節點是小於List2中的,那麼新的連結串列的頭節點必將是List1的頭節點,同理對List2也一樣,那麼在比較完頭節點之後,再將List1中的下一個節點再與List2中的頭節點比較,同樣誰小誰進入新連結串列,然後再比較,直到兩個連結串列比較完,故可用非遞迴或遞迴兩種方式來做。
若連結串列1的頭節點小於連結串列2的頭節點,則小值的頭節點成為合併後連結串列的頭節點。兩個連結串列在第一次合併後,剩下的節點依然是排序的,因此合併這兩個連結串列的步驟和前面一樣,比較頭節點的值,再把小值的頭節點插入合併連結串列中。可以發現,這個合併的過程是重複的,可以定義一個遞迴函式完成這一系列的合併操作。
確定解決辦法後,考慮函式的魯棒性,每當程式碼試圖訪問空指標指向的記憶體時程式都會崩潰,從而導致魯棒性問題。在該問題中,傳入的兩個頭節點都有可能為空,所以我們要對空連結串列進行處理。如果第一個連結串列為空連結串列,那麼直接返回第二個連結串列即可;如果第二個連結串列為空連結串列,那麼直接返回第一個連結串列;如果兩個連結串列都是空連結串列,則返回空。
原始碼
/**
* @program:
* @description: 輸入兩個遞增排序的連結串列,合併這兩個連結串列並使新連結串列中的結點仍然是按照遞增排序的,並返回合併後的頭結點。
* @author: zhouzhixiang
* @create: 2018-11-09 21:40
*/
public class Test16 {
public static class ListNode {
int data;
ListNode next;
}
/**
* 推薦使用此方法
* @param head1 第一個有序列表
* @param head2 第二個有序列表
* @return
*/
public static ListNode merge1(ListNode head1, ListNode head2) {
if (head1 == null) return head2;
if (head2 == null) return head1;
ListNode root = new ListNode();
ListNode move = root;
while (head1 != null && head2 != null) {
if(head1.data < head2.data) {
move.next = head1;
head1 = head1.next;
}else {
root = head2;
root.next = head2;
head2 = head2.next;
}
move = move.next;
}
// 未空連結串列元素處理
if(head1.next!=null) move.next = head1;
if(head2.next!=null) move.next = head2;
// 返回頭結點
return root.next;
}
/**
* 遞迴
* 不推薦
* 遞迴呼叫的時候會有方法入棧,需要更多的記憶體
* @param head1 第一個有序列表
* @param head2 第二個有序列表
* @return
*/
public static ListNode merge2(ListNode head1, ListNode head2) {
if (head1 == null) return head2;
if (head2 == null) return head1;
ListNode root = head1;
if(head1.data < head2.data) {
root.next = merge2(head1.next, head2);
}else {
root = head2;
root.next = merge2(head1, head2.next);
}
return root;
}
}
歡迎加入Java猿社群