- •Глава 1
- •§ 1. Затраты алгоритма для данного входа, алгебраическая сложность
- •§ 1. Затраты алгоритма для данного входа
- •§ 1. Затраты алгоритма для данного входа
- •§ 1. Затраты алгоритма для данного входа
- •§ 1. Затраты алгоритма для данного входа
- •§ 2. Асимптотические оценки (формализм)
- •§ 2. Асимптотические оценки (формализм)
- •§ 2. Асимптотические оценки (формализм)
- •§ 3. Асимптотические оценки (два примера) 23
- •§ 3. Асимптотические оценки (два примера)
- •§ 3. Асимптотические оценки (два примера)
- •§ 3. Асимптотические оценки (два примера)
- •§ 3. Асимптотические оценки (два примера)
- •§ 4. Длина числа как возможный размер входа
- •§ 4. Длина числа как возможный размер входа
- •§ 4. Длина числа как возможный размер входа
- •§ 4. Длина числа как возможный размер входа
- •Глава 2
- •§ 5. Понятие сложности в среднем
- •§ 5. Понятие сложности в среднем
- •Глава 2. Сложность в среднем
- •§ 5. Понятие сложности в среднем
- •Глава 2. Сложность в среднем
- •§ 6. Сортировка и конечные вероятностные пространства.
- •§ 6. Сортировка и конечные вероятностные пространства 47
- •Глава 2. Сложность в среднем
- •§ 6. Сортировка и конечные вероятностные пространства 49
- •Глава 2. Сложность в среднем
- •§ 6. Сортировка и конечные вероятностные пространства 51
- •Глава 2. Сложность в среднем
- •§ 7. Пример медленного роста сложности в среднем
- •§ 7. Пример медленного роста сложности в среднем в сравнении со сложностью в худшем случае
- •Глава 2. Сложность в среднем
- •§ 7. Пример медленного роста сложности в среднем 55
- •Глава 2. Сложность в среднем
- •§ 7. Пример медленного роста сложности в среднем
- •Глава 2. Сложность в среднем
- •§ 8. Функция затрат рандомизированного алгоритма
- •§ 8. Функция затрат рандомизированного алгоритма
- •Глава 2. Сложность в среднем
- •§ 8. Функция затрат рандомизированного алгоритма
- •Глава 2. Сложность в среднем
- •§ 8. Функция затрат рандомизированного алгоритма
- •Глава 2. Сложность в среднем
- •Глава 2. Сложность в среднем
- •Глава 2. Сложность в среднем
- •Глава 2. Сложность в среднем
- •Глава 2. Сложность в среднем
- •Глава 3
- •§ 9. Функции, убывающие по ходу выполнения алгоритма
- •§ 9. Функции, убывающие по ходу выполнения алгоритма 75
- •§ 9. Функции, убывающие по ходу выполнения алгоритма 77
- •§ 9. Функции, убывающие по ходу выполнения алгоритма 79
- •§ 9. Функции, убывающие по ходу выполнения алгоритма 81
- •§ 10. Качество оценок
- •§ 10. Качество оценок
- •§ 10. Качество оценок
- •§ 10. Качество оценок
- •§ 11. Завершимостъ работы алгоритма
- •§ 11. Завершимость работы алгоритма
- •§ 11. Завершимостъ работы алгоритма
- •§ 11. Завершимостъ работы алгоритма
- •§ 12. Вложенные циклы (дополнительные примеры)
- •§ 12. Вложенные циклы (дополнительные примеры)
- •§ 13. Нецелые размеры входа и непрерывные оценочные функции 97
- •§ 13. Нецелые размеры входа и непрерывные оценочные функции
- •§ 13. Нецелые размеры входа и непрерывные оценочные функции 99
- •Глава 4
- •§ 14. Понятие нижней границы сложности
- •§ 14. Понятие нижней границы сложности
- •§ 15. Оптимальные алгоритмы
- •§ 15. Оптимальные алгоритмы
- •§ 15. Оптимальные алгоритмы
- •§ 15. Оптимальные алгоритмы
- •§ 16. Асимптотические нижние границы. Алгоритм, оптимальный по порядку сложности
- •§ 16. Асимптотические нижние границы
- •§ 16. Асимптотические нижние границы
- •§ 17. Нижняя граница сложности в среднем
- •§ 17. Нижняя граница сложности в среднем
- •§ 17. Нижняя граница сложности в среднем
- •§ 17. Нижняя граница сложности в среднем
- •§ 17. Нижняя граница сложности в среднем 125
- •§ 18. Нижние границы сложности рандомизированных алгоритмов. Принцип Яо
- •§18. Нижние границы сложности рандомизированных алгоритмов 127
- •Глава 5
- •§ 19. Битовые операции
- •Глава 5. Битовая сложность
- •§ 19. Битовые операции
- •Глава 5. Битовая сложность
- •§ 20. Наивная арифметика: умножение
- •§ 20. Наивная арифметика: умножение
- •Глава 5. Битовая сложность
- •§ 20. Наивная арифметика: умножение
- •Глава 5. Битовая сложность
- •§ 21. Наивная арифметика: деление с остатком
- •§ 21. Наивная арифметика: деление с остатком
- •Глава 5. Битовая сложность
- •§ 21. Наивная арифметика: деление с остатком
- •Глава 5. Битовая сложность
- •§ 22. Модулярная арифметика
- •§ 22. Модулярная арифметика
- •Глава 5. Битовая сложность
- •§ 22. Модулярная арифметика
- •Глава 5. Битовая сложность
- •§ 22. Модулярная арифметика
- •Глава 5. Битовая сложность
- •§ 23. Булева арифметика
- •§ 23. Булева арифметика
- •Глава 5. Битовая сложность
- •§ 23. Булева арифметика
- •Глава 5. Битовая сложность
- •Глава 5. Битовая сложность
- •Глава 6
- •§ 24. Простейшие рекуррентные уравнения
- •§ 24. Простейшие рекуррентные уравнения
- •§ 24. Простейшие рекуррентные уравнения
- •§ 25. Об одном классе нелинейных рекуррентных соотношений 163
- •§ 25. Об одном классе нелинейных рекуррентных соотношений
- •§ 25. Об одном классе нелинейных рекуррентных соотношений 165
- •§ 25. Об одном классе нелинейных рекуррентных соотношений 167
- •§26. Асимптотические оценки решений рекуррентных неравенств 169
- •§ 26. Асимптотические оценки решений рекуррентных неравенств
- •§ 26. Асимптотические оценки решений рекуррентных неравенств 171
- •§ 27. Добавление нулей
- •§ 27. Добавление нулей 173
- •§ 27. Добавление нулей 175
- •§ 27. Добавление нулей
- •§ 27. Добавление нулей 179
- •Глава 7 Сводимость
- •§ 28. Линейная сводимость
- •Глава 7. Сводимость
- •§ 28. Линейная сводимость
- •Глава 7. Сводимость
- •§ 28. Линейная сводимость
- •Глава 7. Сводимость
- •§ 29. Линейная сводимость и нижние границы сложности
- •§ 29. Линейная сводимость и нижние границы сложности 191
- •Глава 7. Сводимость
- •§ 29. Линейная сводимость и нижние границы сложности 193
- •Глава 7. Сводимость
- •§ 30. Классы PиNp
- •§ 30. Классы р и np
- •Глава 7. Сводимость
- •§ 30. Классы PuNp
- •Глава 7. Сводимость
- •§ 30. Классы PuNp
- •Глава 7. Сводимость
- •§ 31. Существование задач распознавания, не принадлежащих р 201
- •§ 31. Существование задач распознавания, не принадлежащих р. Связь моделей мт и рам
- •Глава 7. Сводимость
- •§ 31. Существование задач распознавания, не принадлежащих р 203
- •Глава 7. Сводимость
- •§ 32. Полиномиальная сводимость. Np-полные задачи
- •§ 32. Полиномиальная сводимость. Np-полные задачи
- •Глава 7. Сводимость
- •Глава 7. Сводимость
- •Глава 7. Сводимость
- •Глава 7. Сводимость
- •Глава 1. Сложности алгоритмов как функции числовых аргументов. Сложность в худшем случае
- •119002, Москва, Большой Власьевский пер., 11. Тел. (499) 241-74-83
Глава 6
Рекуррентные соотношения как средство анализа сложности алгоритмов
§ 24. Простейшие рекуррентные уравнения
Рекуррентные соотношения (уравнения и неравенства) играют существенную роль в анализе алгоритмов. Наиболее известный и простой вид таких соотношений —это линейные рекуррентные уравнения с постоянными коэффициентами.
Пример 24.1. Вернемся к задаче 104, в которой надо доказать, что если к числу, первоначально равному нулю, прибавляется шаг за шагом по единице до достижения значения 2" - 1, n ^ 0, то в целом потребуется 2" - п - 1 переносов единиц в старшие разряды. Коль скоро заранее указан ответ, для доказательства можно использовать индукцию. Но формулу 2" - п - 1 можно вывести, исходя лишь из условия задачи. Обозначим через s(n) исследуемое количество переносов и заметим, что если прибавлением единиц уже получено число 2"-1 - 1 (на это потребуется s(n-l) переносов), то очередное прибавление единицы потребует п - 1 переносов и приведет к числу 2"-1, двоичная запись которого есть 10...0 (количество нулей после единицы равно п-1). Далее в процессе достижения числа 11...1 (п единиц) потребуется еще s(n-l) переносов. Получаем рекуррентное уравнение s(n) = 2s(n - 1) + n - 1 или
s(n)-2s(n-l) = n-l, (24.1)
при этом s(0) = 0. Характеристическое уравнение1, соответствующее рекуррентному уравнению (24.1), имеет вид А - 2 = 0. Общее решение однородного уравнения s(n) - 2s(n - 1) = 0 есть сТ. Правую часть уравнения (24.1) можно записать в виде квазиполинома (п-1)1п. Значение 1 не является корнем характеристического уравнения, по-
1 О методе решения линейных рекуррентных уравнений с постоянными коэффициентами см. в приложении G.
§ 24. Простейшие рекуррентные уравнения
159
этому (24.1) обладает частным решением вида an + Ъ; подставляя это выражение вместо s(n) в (24.1), получаем an + Ъ - 2(а(п - 1) + Ь) = = п - 1, и, приравнивая в левой и правой частях коэффициенты при первой и нулевой степенях п, имеем а = Ъ = -1. Получаем общее решение уравнения (24.1): s(n) = с2" - п - 1. Подбираем значение константы с так, чтобы выполнялось s(0) = 0; для этого должно выполняться с • 2 - 2 = 0, т. е. с = 1. Итак, потребуется 2" - п - 1 переносов единиц в старшие разряды.
Алгоритм, который содержит прямые или косвенные (т. е. при посредстве других алгоритмов) обращения к себе, как известно, называется рекурсивным. Рекуррентные соотношения являются удобным средством анализа сложности рекурсивных алгоритмов.
В следующем примере обсуждается использование рекуррентных уравнений в анализе рекурсивных алгоритмов и указывается один неудачный вид рекурсии.
Пример 24.2. Рассмотрим построение множества Vn всех целых чисел, десятичная запись каждого из которых содержит только цифры 1 и 2, а сумма цифр равна заданному числу n ^ 1. Непосредственно видно, что Vi = {l}, У2 = Ш,2}, У3 = Ш1, 21,12}. В общем случае Vn является, очевидно, объединением двух непересекающихся подмножеств, в первое из которых входят все числа из Vn, оканчивающиеся цифрой 1, во второе — цифрой 2. Если вычеркнуть последнюю цифру, то при п ^ 2 первое подмножество превратится в Уп-ъ второе — в Vn-2. Это наблюдение приводит к рекурсивному алгоритму VRec построения Vn: если п = 1 или п = 2, то результатом будет {1} или соответственно {11,2}; иначе надо найти Vn-x (рекурсивное обращение к алгоритму) и приписать справа ко всем числам этого множества единицу, затем найти Vn-2 (еще одно рекурсивное обращение) и приписать справа ко всем числам этого множества двойку, после чего построить объединение двух получившихся множеств.
Не составляет труда заметить, что алгоритм VRec избыточно сложен (о чем еще будет идти речь). Но анализ сложности часто приходится проводить и для «плохих» алгоритмов — например, чтобы показать их практическую непригодность.
Прежде чем исследовать временную сложность этого алгоритма, установим, чему равно число v(n) элементов Vn. Мы видим, что v(l) = l, v(2) = 2, v(n)=v(n-l)+v(n-2), n = 3,4, ... Таким образом, v(n) равно (п-Ы)-му числу Фибоначчи: v(n)=Fn+1. Явное выражение v(n) через п можно получить, воспользовавшись формулой Бине (10.2), которая сама может быть выведена с помощью общего
160 Глава 6. Рекуррентные соотношения и сложность алгоритмов
метода решения линейных рекуррентных уравнений с постоянными коэффициентами.
Используя рекуррентные уравнения, мы можем определить количество у(п) преобразований чисел при построении множества Vn по описанному алгоритму (каждое из этих преобразований состоит в приписывании справа к числу единицы или двойки). Мы можем также определить число z(n) выполняемых операций объединения множеств. Очевидно, имеет место уравнение у(п)=у(п-1) + + y(n-2) +Fn +Fn-1, которое мы перепишем в более удобном виде и добавим начальные значения:
y(n)-y(n-1)-y(n-2)=Fn+1, (24.2)
у(2) = у(1) = 0. Аналогично, имеем
z(n)-z(n-1)-z(n-2) = 1, (24.3)
z(2)=z(1) = 0.
Начнем со второго уравнения. Будем, как обычно, прибегать к обозначениям
, 1 + а/5 г 1-У5
Ф == ˜ == .
Непосредственно видно, что -1 является частным решением нашего рекуррентного уравнения (это частное решение можно получить и общим методом: правая часть является квазиполиномом 1", при этом 1 не есть корень характеристического уравнения
А2 - А - 1 = 0, (24.4)
и, следовательно, существует частное решение вида c1", где с — полином нулевой степени, т. е. константа; подстановка в (24.3) дает с = -1). Корнями уравнения (24.4) служат числа фи ˜ , входящие в формулу Бине, и общее решение уравнения (24.3) может быть записано в виде z(n) = С1фп + С2 ˜п - 1. Начальные условия z(2) = z(1) = 0 приводят нас к системе
15 "ч 2 s 1 5 ~\ 2
Получаем
C1 = 4=, С2 = - ˜=. (24.5)
а/5 а/5