Sword は、offer25 を参照します。 2 つの順序付きリンク リストをマージします。
方法 1: 再帰
アイデア: 2 つのリンク リストでマージ操作を次のように再帰的に定義できます (空のリンク リストなどの特殊なケースは無視します): {
list 1 [ 0 ] + merge ( list 1 [ 1 : ] , list 2 ) list 1 [ 0 ] < list 2 [ 0 ] list 2 [ 0 ] + merge ( list 1 , list 2 [ 1 : ] ) それ以外の場合 \left\{\begin{array}{ll} \operatorname{list} 1 [0]+ \operatorname{merge}(\text { list } 1[1:], \text { list } 2) & \text { list } 1[0]<\operatorname{list} 2[0] \\ \text { list } 2[0]+\text { merge }(\text { list } 1, \text { list } 2[1:]) & \text { それ以外の場合 } \end{array}\right。{
リスト1 [ 0 ]+マージ( リスト 1 [ 1: ] 、 リスト 2 ) リスト 2 [ 0 ]+ マージ ( リスト 1 、 リスト 2 [ 1: ] ) リスト 1 [ 0 ]<リスト2 [ 0 ]それ以外の場合
つまり、2 つの連結リストのうち先頭の値が小さいノードが、残りの要素のマージ演算結果とマージされます。
アルゴリズム
上記の再帰プロセスを直接モデル化しますが、境界ケースを考慮する必要があります。
l1 または l2 が最初から空のリンク リストである場合、操作をマージする必要はなく、空ではないリンク リストを返すだけで済みます。それ以外の場合は、リンク リストのヘッド ノードの l1 または l2 のどちらが小さい値を持つかを判断し、結果に追加する次のノードを再帰的に決定する必要があります。2 つのリンクされたリストのうちの 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: 反復
アイデア: 反復法を使用して上記のアルゴリズムを実装できます。l1 と l2 のどちらも空のリンク リストでない場合は、どちらのリンク リストの先頭ノードの値が小さいかを判断し、値が小さい方のノードを結果に追加します。ノードが結果に追加されると、対応するリンク リストのノードが追加されます。 1 つ後ろに移動します。
アルゴリズム
1. センチネル ノードのプリヘッドを設定します。これにより、最後にマージされたリンク リストをより簡単に返すことができます。
2. prev ポインタを維持します。必要なのは、その next ポインタを調整することです。次に、l1 または l2 が null を指すまで次のプロセスを繰り返します。
l1 の現在のノードの値が l2 以下の場合、l1 の現在のノードを前のノードの後ろに接続し、l1 ポインタを 1 つ後方に移動します。それ以外の場合は、l2 に対して同じことを行います。どの要素を後ろに接続する場合でも、前に 1 つ後ろに移動する必要があります。
ループが終了すると、l1 と l2 の少なくとも 1 つは空ではありません。2 つの入力リンク リストは両方とも順序付けされているため、どちらのリンク リストが空でなくても、そこに含まれるすべての要素は、以前にマージされたすべてのリンク リストよりも丸められます。これは、単純に空ではないリンク リストをマージされたリストに追加し、マージされたリストを返すことを意味します。
参考文献
[1] https://leetcode.cn/problems/merge-two-sorted-lists/solution/he-bing-liang-ge-you-xu-lian-biao-by-leetcode-solu/