mirror of
https://github.com/krahets/hello-algo.git
synced 2026-07-22 11:26:07 +00:00
88 lines
7.4 KiB
Markdown
88 lines
7.4 KiB
Markdown
# Упражнения
|
||
|
||
## Вопросы для самопроверки
|
||
|
||
### Пропустит ли этот алгоритм некоторые перестановки
|
||
|
||
Алгоритм поиска с возвратом пытается построить все перестановки, перебирая числа в порядке `1, 2, 3`. Выбрав число `x`, он:
|
||
|
||
1. добавляет `x` в конец текущего пути;
|
||
2. помечает `x` как «использованное»;
|
||
3. рекурсивно заполняет следующую позицию.
|
||
|
||
После возврата из рекурсии ученик удалил `x` только из конца пути и перешел к следующему числу.
|
||
|
||
<!-- numbered-subquestions -->
|
||
|
||
1. Какую перестановку алгоритм получит первой? Сможет ли он получить все 6 перестановок?
|
||
2. Достаточно ли перед возвратом на предыдущий уровень удалить число из конца пути? Если нет, что еще нужно сделать и почему?
|
||
|
||
??? success "Ответ"
|
||
|
||
1. Первой получится перестановка `[1, 2, 3]`, но алгоритм не сможет получить все перестановки. Хотя после возврата путь становится короче,
|
||
числа 1, 2 и 3 по-прежнему помечены как «использованные», поэтому в последующих ветвях не останется доступных чисел.
|
||
|
||
2. Нет. После удаления `x` из конца пути нужно также снова пометить `x` как «неиспользованное».
|
||
Текущий путь и отметки «использовано» вместе описывают состояние поиска. При выборе изменяются обе части состояния, поэтому при возврате нужно восстановить обе,
|
||
чтобы другие ветви могли снова выбрать `x`.
|
||
|
||
### Важен ли порядок выбора чисел
|
||
|
||
Дан упорядоченный массив `[2, 3, 5]` и целевое значение 5. Каждое число разрешено выбирать повторно.
|
||
Алгоритм требует, чтобы числа в каждом пути поиска располагались только в неубывающем порядке.
|
||
|
||
<!-- numbered-subquestions -->
|
||
|
||
1. Какие различные комбинации можно получить?
|
||
2. Почему один и тот же набор чисел не нужно повторно перебирать в разном порядке? Какую роль играет ограничение «по неубыванию»?
|
||
3. Текущий путь равен `[3]`, до цели не хватает 2, а следующий возможный элемент равен 3. Почему теперь можно прекратить проверку всех следующих элементов на этом уровне?
|
||
|
||
??? success "Ответ"
|
||
|
||
1. Различные комбинации: `[2, 3]` и `[5]`.
|
||
|
||
2. В этой задаче `[2, 3]` и `[3, 2]` считаются одной комбинацией: порядок выбора чисел не влияет на ответ.
|
||
Требование располагать числа в пути по неубыванию позволяет сразу исключить из поиска повторные комбинации наподобие `[3, 2]`.
|
||
|
||
3. До цели осталось 2, а возможный элемент 3 уже больше 2. Поскольку массив упорядочен,
|
||
все последующие элементы будут еще больше и также не смогут войти в текущую комбинацию. Поэтому проверку этого уровня можно сразу завершить.
|
||
|
||
### Куда можно поставить следующего ферзя
|
||
|
||
Ферзи расставляются по строкам на доске `4 × 4`; индексы строк и столбцов начинаются с 0.
|
||
Ферзи уже стоят на позициях `(0, 1)` и `(1, 3)`. Следующего ферзя нужно поставить в строке 2.
|
||
|
||
<!-- numbered-subquestions -->
|
||
|
||
1. Какие столбцы исключаются из-за того, что в них уже есть ферзь?
|
||
2. Какие из оставшихся позиций исключаются из-за расположения на одной диагонали с другим ферзем?
|
||
3. Какие позиции в строке 2 еще можно попробовать?
|
||
|
||
??? success "Ответ"
|
||
|
||
1. В столбцах 1 и 3 уже стоят ферзи, поэтому позиции `(2, 1)` и `(2, 3)` исключаются.
|
||
|
||
2. Среди оставшихся позиций `(2, 2)` находится на одной диагонали с `(1, 3)`, поэтому ее также нужно исключить.
|
||
Позиция `(2, 0)` не совпадает по столбцу ни с одним из уже поставленных ферзей и не лежит с ними на одной диагонали.
|
||
|
||
3. В строке 2 можно попробовать только позицию `(2, 0)`.
|
||
|
||
Этот шаг показывает лишь, что текущее расположение допустимо. Если завершить доску затем не удастся, потребуется вернуться и попробовать другие, более ранние варианты.
|
||
|
||
## Задачи по программированию
|
||
|
||
### Все перестановки различных элементов
|
||
|
||
Массив целых чисел `nums` содержит хотя бы один элемент, и все его элементы попарно различны.
|
||
Перечислите все возможные порядки, в которых каждый элемент используется ровно один раз, и верните каждый порядок как отдельный массив.
|
||
Порядок самих перестановок в результате не имеет значения.
|
||
Используйте поиск с возвратом и булев массив, отмечающий, выбран ли элемент из каждой позиции входного массива в текущую перестановку.
|
||
|
||
??? tip "Подсказки"
|
||
|
||
1. Глубина рекурсии показывает, какую по счету позицию перестановки нужно заполнить
|
||
2. На каждом уровне пробуйте только еще не использованные элементы
|
||
3. Когда длина пути станет равна длине `nums`, добавьте в ответ копию пути
|
||
|
||
[LeetCode](https://leetcode.com/problems/permutations/){ .rounded-button .exercise-button target="_blank" rel="noopener noreferrer" }
|