## Объяснение решения задачи "Merge Two Sorted Lists" на LeetCode (№21)
Задача:
Дан два отсортированных односвязных списка `l1` и `l2`. Необходимо слить эти списки в один отсортированный список, не изменяя исходные списки.
Решение:
1. Инициализация: Создаем новую переменную `head` для головы нового списка, и `tail` для последнего элемента. Устанавливаем `head = None` и `tail = None`.
2. Сравнение: Пока `l1` и `l2` не пусты, сравниваем значения `l1.val` и `l2.val`.
- Если `l1.val` меньше, добавляем узел `l1` в конец нового списка. Обновляем `tail = l1` и `l1 =
l1.next `.
- Если `l2.val` меньше, добавляем узел `l2` в конец нового списка. Обновляем `tail = l2` и `l2 =
l2.next `.
- Если `l1.val` и `l2.val` равны, выбираем один из узлов, добавляем его в конец нового списка и обновляем соответствующий список и `tail`.
3. Добавление остатка: После того, как один из списков станет пустым, добавляем все оставшиеся узлы другого списка в конец нового списка.
4. Возврат результата: Возвращаем `head` - голову нового списка.
Код на Java:
```java
/
Definition for singly-linked list.
public class ListNode {
int val;
ListNode next;
ListNode() {}
ListNode(int val) { this.val = val; }
ListNode(int val, ListNode next) { this.val = val; this.next = next; }
}
/
class Solution {
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
ListNode head = null;
ListNode tail = null;
while (l1 != null && l2 != null) {
if (l1.val <= l2.val) {
if (head == null) {
head = l1;
tail = l1;
} else {
tail.next = l1;
tail = l1;
}
l1 = l1.next;
} else {
if (head == null) {
head = l2;
tail = l2;
} else {
tail.next = l2;
tail = l2;
}
l2 = l2.next;
}
}
while (l1 != null) {
tail.next = l1;
tail = l1;
l1 = l1.next;
}
while (l2 != null) {
tail.next = l2;
tail = l2;
l2 = l2.next;
}
return head;
}
}
```
Пояснения:
- head: указывает на начало нового списка.
- tail: указывает на последний добавленный узел в новый список.
- l1, l2: исходные списки, которые мы сливаем.
- while (l1 != null && l2 != null): цикл продолжается, пока оба списка не опустеют.
- if (l1.val <= l2.val): сравниваем значения узлов и добавляем меньший в конец нового списка.
- if (head == null): если `head` пуст, значит, новый список еще не создан, и мы устанавливаем `head` и `tail` на добавляемый узел.
- else: если `head` не пуст, значит, у нового списка уже есть узлы, поэтому мы добавляем новый узел в конец `
tail.next ` и обновляем `tail`.
- while (l1 != null): после того, как `l2` станет пустым, добавляем оставшиеся узлы из `l1` в конец нового списка.
- while (l2 != null): после того, как `l1` станет пустым, добавляем оставшиеся узлы из `l2` в конец нового списка.
- return head: возвращаем `head` нового списка.