Как узнать
области или острова в сетке, всё, что достижимо из старта, все пути или задача на дереве, которая решается от листьев вверх.
Как решать такие задачи
- Спроси, что узлу нужно от потомков, чтобы получить свой ответ: глубина, сумма, да или нет.
- Напиши f(node). Если node — none, верни ответ для пустого дерева.
- Вызови f(node.left) и f(node.right) и объедини два ответа со своим val.
- Если информация идёт сверху вниз (накопленная сумма, путь до узла), передавай её аргументом.
Вариант: Сверху вниз
То же, но сведения передаём сверху вниз: узел получает от родителя то, что известно о пути от корня, и передаёт детям дальше. Так удобно, когда вопрос про путь от корня, а не про поддерево.
- Спроси, что узлу нужно знать о пути над ним: сумму на данный момент, число, собранное из цифр, допустимый диапазон.
- Передавай это аргументом обоим потомкам, учтя свой val.
- Решай в листьях, а ответ отправляй вверх: true, если хоть один потомок сказал true. Можно вернуться сразу, как только он скажет.
- В задаче про сумму чисел от корня до листьев вниз передают number × 10 + val, а числа в листьях складывают.
- Чтобы проверить дерево поиска, передавай вниз границы: левый потомок получает (low, node.val), правый — (node.val, high), и каждый val должен в них попадать.
Вариант: Граф
То же, но в графе к одной вершине могут вести разные пути и бывают циклы. Поэтому посещённые вершины отмечаем, чтобы не зайти в них снова.
- Определи, что здесь вершина (узел, клетка, состояние) и кто её соседи.
- Напиши dfs(вершина): сначала добавь её в visited, потом вызови dfs для каждого соседа, которого там ещё нет.
- Запускай dfs из каждой вершины, которую ещё никто не посетил. Каждый такой запуск — новая компонента связности.
- Чтобы что-то посчитать, возвращай это из dfs и собирай ответы вызовов ниже: размер, путь, нашлась ли цель.
Вариант: Сетка
То же, но на сетке: клетки — это вершины, а соседние клетки связаны. Обход из клетки находит всю её область, например весь остров.
- Определи, что здесь вершина (клетка, узел, состояние) и кто её соседи.
- Напиши dfs(вершина): сначала отметь её посещённой, потом вызови dfs для каждого непосещённого соседа.
- Запускай dfs из каждой вершины, которую ещё никто не посетил. Каждый такой запуск — новая область.
- Чтобы что-то посчитать, возвращай это из dfs и собирай ответы вызовов ниже: размер, глубину, путь.
Где встречается
- Обход папок. find и du заходят в папку, потом в её первую подпапку, и так до дна, а потом возвращаются. du складывает размер папки из размеров подпапок: ответ дерева из ответов поддеревьев.
- Сборка мусора. Сборщик мусора в Java начинает с переменных программы и идёт по ссылкам вглубь, отмечая всё живое. Всё, до чего он не дошёл, — мусор.
- Заливка. Инструмент «Заливка» в графическом редакторе закрашивает пиксель и идёт к соседям того же цвета, пока область не кончится. Классическая версия — обход области в глубину.