Files
hello-algo/ru/docs/chapter_divide_and_conquer/exercises.md
T
Yudong Jin 9135647d93 Add translated chapter exercise pages (#1941)
Add dedicated chapter exercise sections and generated exercise pages for the English, Japanese, and Russian editions.

Add navigation for all published languages while keeping Taiwan Traditional Chinese exercise pages generated at build time.
2026-07-19 04:25:58 +08:00

99 lines
7.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!-- Автоматически создано utils/exercises/publish_exercises.py; не редактируйте напрямую. -->
# Упражнения
## Вопросы для самопроверки
### Какие задачи подходят для метода «разделяй и властвуй»
Ученик хочет решить следующие задачи способом «разделить на две половины, решить каждую отдельно, затем объединить результаты».
Для каждой задачи выберите одно из утверждений: «подходит для метода “разделяй и властвуй”», «разделение возможно, но не уменьшает общий объем работы» или «половины нельзя решить независимо». Объясните свой выбор.
<!-- numbered-subquestions -->
1. Отсортировать неупорядоченный массив;
2. найти максимальный элемент массива;
3. последовательно выполнить набор операций стека `push(x)` и `pop()`, выводя элемент, полученный при каждой операции `pop()`.
??? success "Ответ"
1. Подходит: массив делится пополам, обе половины независимо сортируются, а затем сливаются за $O(n)$ — именно так работает сортировка слиянием.
2. Разделение возможно, но оно не уменьшит общий объем работы: в обеих половинах в сумме все равно нужно проверить все $n$ элементов,
поэтому, как и при прямом обходе, потребуется $O(n)$ времени.
3. Половины нельзя решить независимо: содержимое стека в начале второй половины операций зависит от результата первой,
поэтому решить их независимо, не зная результатов друг друга, невозможно.
### Как быстрое возведение в степень уменьшает число вычислений
Рекурсивная функция ниже вычисляет $x^n$ методом «разделяй и властвуй»:
```python
def fast_pow(x, n):
if n == 0:
return 1
half = fast_pow(x, n // 2)
if n % 2 == 0:
return half * half
return half * half * x
```
Функция вызывается как `fast_pow(3, 5)`.
<!-- numbered-subquestions -->
1. Какие значения последовательно принимает параметр `n` при рекурсивных вызовах?
2. Какие значения поочередно возвращаются на каждом уровне, начиная с самого глубокого?
3. Почему результат нужно сначала сохранить в `half`, а не дважды записывать `fast_pow(x, n // 2)`?
??? success "Ответ"
1. Параметр последовательно принимает значения `5 → 2 → 1 → 0`: на каждом шаге показатель степени уменьшается вдвое до достижения условия завершения.
2. При `n = 0` возвращается 1; при `n = 1` возвращается $1×1×3=3$;
при `n = 2` — $3×3=9$; при `n = 5` — $9×9×3=243$.
3. Если записать `fast_pow(x, n // 2)` по обе стороны умножения, два рекурсивных вызова будут решать одну и ту же подзадачу.
Когда результат сохраняется в `half`, на каждом уровне выполняется только один рекурсивный вызов, а глубина рекурсии составляет примерно $\log n$;
два вызова привели бы к множеству повторных вычислений.
### Разделение левого и правого поддеревьев по последовательностям обхода
Двоичное дерево без повторяющихся узлов имеет следующие последовательности прямого и симметричного обходов:
- прямой обход: `[A, B, D, E, C]`
- симметричный обход: `[D, B, E, A, C]`
Выполните только разделение на уровне корневого узла: продолжать рекурсию и рисовать все дерево не требуется.
<!-- numbered-subquestions -->
1. Какой узел является корневым?
2. Какие участки симметричного обхода соответствуют левому и правому поддеревьям?
3. Какие участки прямого обхода соответствуют левому и правому поддеревьям? Какие непосредственные дочерние узлы имеет корень?
??? success "Ответ"
1. Первый узел прямого обхода является корневым, поэтому корень — `A`.
2. Узел `A` делит симметричный обход на две части: левому поддереву соответствует `[D, B, E]`, правому — `[C]`.
3. Левое поддерево содержит 3 узла, поэтому следующие после корня `A` 3 элемента прямого обхода относятся к левому поддереву:
`[B, D, E]`. Оставшийся участок `[C]` относится к правому поддереву.
Следовательно, левый дочерний узел корня — `B`, а правый — `C`.
## Задачи по программированию
### Быстрое возведение в степень
Даны вещественное число `x` и целое число `n`. Вычислите $x^n$, не используя встроенную функцию возведения в степень.
Примените рекурсивный метод «разделяй и властвуй»: каждый раз уменьшайте показатель степени вдвое и повторно используйте уже вычисленный результат подзадачи.
В этой задаче $x^0=1$, в том числе при `x = 0`; если `n < 0`, гарантируется, что `x != 0`, а ответ можно преобразовать к $(1/x)^{-n}$.
??? tip "Подсказки"
1. При n, равном 0, ответ равен 1
2. Вычислив x в степени n // 2, сохраните результат в half и не выполняйте рекурсивный вызов второй раз
3. Если n < 0, сначала замените x на 1 / x, а n — на -n; в C++ или Java предварительно преобразуйте n в 64-битное целое число, чтобы избежать переполнения при смене знака у минимального 32-битного целого
[LeetCode](https://leetcode.com/problems/powx-n/){ .rounded-button .exercise-button target="_blank" rel="noopener noreferrer" }