ここにカタログタイトルを書く
1.タイトルの説明
2.問題解決のアイデア
アイデア1:再帰
次のように、2つのリンクリストでマージ操作を再帰的に定義できます(空のリンクリストなどの境界条件を無視します)。
list1 [0] + merge(list1 [1:]、list2)list1 [0] <list2 [0]
list2 [0] + merge(list1、list2 [1:])それ以外の場合
つまり、2つのリンクリストのヘッド値が小さいノードが、残りの要素のマージ操作の結果とマージされます。
アルゴリズム
上記の再帰的プロセスを直接モデル化すると同時に、境界条件を考慮する必要があります。
l1またはl2が最初から空のリンクリストである場合、マージする操作はないため、空でないリンクリストを返すだけで済みます。それ以外の場合は、リンクリストのヘッドノードの値が小さい方をl1とl2のどちらかを判別してから、結果に追加する次のノードを再帰的に決定する必要があります。2つのリンクリストのいずれかが空の場合、再帰は終了します。
アイデア2:反復
反復法を使用して、上記のアルゴリズムを実装できます。l1とl2の両方が空のリンクリストでない場合、l1とl2のどちらがリンクリストのヘッドノードの値が小さいかを判断し、値が小さいノードを結果に追加します。ノードが結果に追加された場合、対応するリンクリストにあります。のノードは1ビット戻ります。
アルゴリズム
最初に、センチネルノードのプリヘッドを設定します。これにより、最後にマージされたリンクリストに簡単に戻ることができます。前のポインタを維持し、次のポインタを調整する必要があります。次に、l1またはl2がnullを指すまで、次のプロセスを繰り返します。l1の現在のノードの値がl2以下の場合、l1の現在のノードを前のノードの後ろに接続してポインターを移動します。 l1の1ビット後方。それ以外の場合は、l2についても同じことを行います。どの要素に従うかに関係なく、prevを1ビット後方に移動する必要があります。
ループの終わりでは、l1とl2の最大1つが空ではありません。2つの入力リンクリストは順番に並んでいるため、どちらのリンクリストが空でなくても、そこに含まれるすべての要素は、以前にマージされたリンクリストのすべての要素よりも大きくなります。これは、空でないリンクリストをマージされたリンクリストの後ろに接続して、マージされたリンクリストに戻るだけでよいことを意味します。
3.コードの実装
アイデア1のコード:
class Solution {
public ListNode mergeTwoLists(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;
}
}
}
アイデア2のコード:
class Solution {
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;
}
// 合并后 l1 和 l2 最多只有一个还未被合并完,我们直接将链表末尾指向未合并完的链表即可
prev.next = l1 == null ? l2 : l1;
return prehead.next;
}
}