This commit is contained in:
krahets
2026-04-14 18:06:14 +08:00
parent 065a978848
commit e53a7f2498
93 changed files with 565 additions and 570 deletions
@@ -8,7 +8,7 @@ comments: true
!!! question
Дан массив положительных целых чисел `nums` и целое положительное значение `target` . Найдите все возможные комбинации, сумма элементов которых равна `target` . Во входном массиве нет повторяющихся элементов, и каждый элемент можно выбирать неограниченное число раз. Верните эти комбинации в виде списка; в результате не должно быть повторяющихся комбинаций.
Дан массив положительных целых чисел `nums` и целое положительное значение `target` . Найдите все возможные комбинации, сумма элементов которых равна `target` . Во входном массиве нет повторяющихся элементов, и каждый элемент можно выбирать неограниченное число раз. Верните эти комбинации в виде списка. В результате не должно быть повторяющихся комбинаций.
Например, для входного множества $\{3, 4, 5\}$ и целевого значения $9$ решениями будут $\{3, 3, 3\}$ и $\{4, 5\}$ . При этом важно учитывать два обстоятельства.
@@ -17,7 +17,7 @@ comments: true
### 1.   Отталкиваемся от решения задачи о перестановках
Как и в задаче о перестановках, можно представлять построение подмножеств как результат последовательности выборов и во время выбора динамически обновлять "сумму элементов"; когда эта сумма становится равной `target` , соответствующее подмножество записывается в список результатов.
Как и в задаче о перестановках, можно представлять построение подмножеств как результат последовательности выборов и во время выбора динамически обновлять «сумму элементов». Когда эта сумма становится равной `target` , соответствующее подмножество записывается в список результатов.
Однако в отличие от задачи о перестановках **в этой задаче элементы множества можно выбирать неограниченное число раз**, поэтому нам не нужен булев список `selected` для записи того, был ли выбран элемент. Можно слегка изменить код для перестановок и получить первоначальную версию решения:
@@ -542,7 +542,7 @@ comments: true
### 2.   Обрезка повторяющихся подмножеств
**Поэтому стоит выполнять устранение дубликатов прямо во время поиска, с помощью обрезки**. Посмотрите на рисунок 13-11: повторяющиеся подмножества возникают тогда, когда элементы массива выбираются в разном порядке, например так.
**Поэтому стоит выполнять устранение дубликатов прямо во время поиска, с помощью обрезки**. Как видно на рисунке 13-11, повторяющиеся подмножества возникают тогда, когда элементы массива выбираются в разном порядке, например так.
1. Если в первом и втором раундах выбрать соответственно $3$ и $4$ , то будут сгенерированы все подмножества, содержащие эти два элемента, и их можно обозначить как $[3, 4, \dots]$ .
2. После этого, если в первом раунде выбрать $4$ , **то во втором раунде нужно пропустить $3$** , потому что подмножества $[4, 3, \dots]$ полностью дублируют подмножества, уже построенные на шаге `1.` .
@@ -557,7 +557,7 @@ comments: true
<p align="center"> Рисунок 13-11 &nbsp; Повторяющиеся подмножества из-за разного порядка выбора </p>
В общем виде, если входной массив имеет вид $[x_1, x_2, \dots, x_n]$ , а последовательность выборов в ходе поиска равна $[x_{i_1}, x_{i_2}, \dots, x_{i_m}]$ , то она должна удовлетворять условию $i_1 \leq i_2 \leq \dots \leq i_m$ ; **все последовательности выборов, не удовлетворяющие этому условию, приводят к дубликатам и должны отсекаться**.
В общем виде, если входной массив имеет вид $[x_1, x_2, \dots, x_n]$ , а последовательность выборов в ходе поиска равна $[x_{i_1}, x_{i_2}, \dots, x_{i_m}]$ , то она должна удовлетворять условию $i_1 \leq i_2 \leq \dots \leq i_m$. **Все последовательности выборов, не удовлетворяющие этому условию, приводят к дубликатам и должны отсекаться**.
### 3. &nbsp; Реализация кода
@@ -566,7 +566,7 @@ comments: true
Помимо этого, мы внесем в код еще два улучшения.
- Перед началом поиска отсортируем массив `nums` . Тогда при обходе всех вариантов **можно сразу прервать цикл, как только сумма подмножества превысит `target`** , потому что все последующие элементы будут еще больше и их сумма тоже превысит `target` .
- Откажемся от отдельной переменной суммы `total` и **будем учитывать сумму через вычитание из `target`** ; когда `target` станет равным $0$ , решение фиксируется.
- Откажемся от отдельной переменной суммы `total` и **будем учитывать сумму через вычитание из `target`**. Когда `target` станет равным $0$ , решение фиксируется.
=== "Python"
@@ -1098,11 +1098,11 @@ comments: true
!!! question
Дан массив положительных целых чисел `nums` и целое положительное значение `target` . Найдите все возможные комбинации, сумма элементов которых равна `target` . **Во входном массиве могут присутствовать повторяющиеся элементы, и каждый элемент разрешено выбирать только один раз**. Верните эти комбинации в виде списка; в результате не должно быть повторяющихся комбинаций.
Дан массив положительных целых чисел `nums` и целое положительное значение `target` . Найдите все возможные комбинации, сумма элементов которых равна `target` . **Во входном массиве могут присутствовать повторяющиеся элементы, и каждый элемент разрешено выбирать только один раз**. Верните эти комбинации в виде списка. В результате не должно быть повторяющихся комбинаций.
По сравнению с предыдущей задачей **во входном массиве теперь могут присутствовать повторяющиеся элементы**, и это создает новую проблему. Например, если дан массив $[4, \hat{4}, 5]$ и целевое значение $9$ , то существующий код вернет результат $[4, 5], [\hat{4}, 5]$ , то есть с повторяющимся подмножеством.
**Причина появления дублей в том, что равные элементы выбираются несколько раз в одном и том же раунде**. На рисунке 13-13 в первом раунде существует три варианта выбора, и два из них равны $4$ ; из-за этого появляются две дублирующиеся ветви поиска и, соответственно, повторяющиеся подмножества. Точно так же два элемента $4$ во втором раунде тоже порождают дубликаты.
**Причина появления дублей в том, что равные элементы выбираются несколько раз в одном и том же раунде**. На рисунке 13-13 в первом раунде существует три варианта выбора, и два из них равны $4$. Из-за этого появляются две дублирующиеся ветви поиска и, соответственно, повторяющиеся подмножества. Точно так же два элемента $4$ во втором раунде тоже порождают дубликаты.
![Повторяющиеся подмножества из-за равных элементов](subset_sum_problem.assets/subset_sum_ii_repeat.png){ class="animation-figure" }