Рекурсия, итерация и оценки сложности алгоритмов
Исключительные ситуации и работа с последовательностями
Часто при решении задачи, связанной с обработкой последовательно поступающих элементов, нет необходимости запоминать их, складывая в массив. Это позволяет экономить и память и время. Последняя задача предыдущей секции может быть слегка переформулирована.
Задача 5.10. Напишите программу, вводящую последовательность целых чисел, и печатающую количество ее максимальных элементов.
Подобная формулировка накладывает определенные ограничения на то, как должна быть устроена программа. Во-первых, не разрешается использовать массив для хранения элементов последовательности. Во-вторых, после ввода каждого очередного элемента (а часто и до ввода самого первого) программа обязана в принципе уметь напечатать ту характеристику последовательности, вычислению которой она посвящена. В-третьих, программа должна уметь работать со сколь угодно длинными последовательностями.
Текст программы
public class NumMaxSeqv1 { public static void main(String[] args) { int max = Integer.MIN_VALUE; int nMax = 0; try { while (true) { int x = Xterm.inputInt("Очередной элемент x -> "); if (x > max) { max = x; nMax = 1; } else if (x == max) nMax += 1; Xterm.println("Количество макс. элементов = " + nMax); } } catch(Exception e) { ; } } }
Эта программа использует конструкцию try-catch, предназначенную для обработки исключительных ситуаций (называемых и просто исключениями). Интерпретатор байт-кода пытается выполнить все действия, указанные в блоке try ( try переводится именно так — пытаться ). Если это удается, то содержимое блока catch не оказывает никакого влияния на ход выполнения программы. Однако, если в процессе выполнения блока try возникает исключительная ситуация — нечто препятствующее продолжению нормального выполнения программы, то управление немедленно передается блоку catch ( catch означает поймать ).
В приведенной выше программе содержимое блока try помещено в бесконечный цикл, что гарантирует выход из него только при возникновении исключительной ситуации. В данном случае причина возникновения такой ситуации может быть только одна — ошибка при вводе очередного числа. Если это случается, то управление передается в блок catch, который в данном случае ничего не делает, и программа завершает работу.
Приведенная программа печатает количество максимальных элементов после ввода каждого очередного элемента. Если это не желательно, то оператор вывода результата перемещают в блок catch:
Фрагмент программы (NumMaxSeqv2.java)
try { while (true) { int x = Xterm.inputInt("Очередной элемент x -> "); if (x > max) { max = x; nMax = 1; } else if (x == max) nMax += 1; } } catch(Exception e) { Xterm.println("\nКоличество макс. элементов = " + nMax); }
Заметьте, что для программ, предусматривающих обработку исключительных ситуаций, теряет свою актуальность совет о необходимости дописывания фразы throws Exception в строку, начинающую определение метода main.
Задачи для самостоятельного решения
Задача 5.11. Напишите программу, вычисляющую факториал введенного натурального числа, не использующую ни итерации, ни рекурсии (имеющую сложность ).
Указание Воспользуйтесь тем, что факториал — очень быстро растущая функция, а множество — ограничено, и поэтому любая программа, работающая с величинами типа int, способна вычислить факториал только очень небольших чисел.
Задача 5.12. Напишите программу, перемножающую два натуральных числа, которая не использует операции умножения.
Задача 5.13. Напишите программу, перемножающую два натуральных числа, которая не использует операции умножения, и имеет при этом логарифмическую сложность.
Указание Можете попробовать разобраться в программе, решающей задачу 5.5. В ней выполняется более сложное действие — квадратная матрица возводится в степень за логарифмическое время.
Задача 5.14. Напишите программу, вводящую целое число и натуральное , вычисляющую и печатающую степень без использования вызова функции возведения в степень.
Задача 5.15. Напишите программу (быстрое возведение в степень), возводящую целое число в целую неотрицательную степень без вызова функции возведения в степень с временной сложностью .
Задача 5.16. Напишите программу, печатающую сумму квадратов всех натуральных чисел от 1 до введенного натурального , которая имела бы константную сложность, т.е. не использовала бы ни итерации, ни рекурсии.
Задача 5.17. Напишите программу, вводящую натуральное число, и печатающую Yes, если оно является простым и No иначе.
Задача 5.18. Напишите программу, печатающую -ое простое число.
Задача 5.19. Напишите рекурсивную программу, печатающую биноминальный коэффициент для целых и , где . Для неотрицательных и имеют место следующие соотношения: , .
Задача 5.20. Напишите программу, вводящую имя пользователя (с применением метода inputChars ), которая затем приветствует его.
Задача 5.21. Напишите программу, печатающую количество нулевых элементов в заданном целочисленном массиве.
Задача 5.22. Напишите программу, которая вводит с клавиатуры непустой массив целых чисел, и печатает Yes, если массив симметричен, и No иначе.
Задача 5.23. Напишите программу, которая вводит с клавиатуры непустой массив целых чисел, циклически сдвигает элементы массива вправо на одну позицию, и печатает результат. Цикличность означает, что последний элемент массива становится самым первым его элементом.
Задача 5.24. Напишите программу, которая вводит с клавиатуры непустой массив целых чисел, циклически сдвигает элементы массива вправо на позиций, и печатает результат. Число вводится с клавиатуры, а сложность программы должна быть .
Задача 5.25. Напишите программу, которая вводит с клавиатуры непустой массив целых чисел, заменяет все элементы массива, кроме крайних, на полусумму соседей, и печатает результат.
Задача 5.26. Напишите программу (линейный поиск), определяющую первое вхождение заданного целого числа в массив целых чисел, заведомо содержащий это число.
Задача 5.27. Напишите программу, вводящую последовательность целых чисел, и печатающую количество различных значений квадратов ее элементов.
Задача 5.28. Напишите программу, вводящую последовательность вещественных чисел, и печатающую среднее арифметическое ее элементов (для непустой последовательности).
Задача 5.29. Напишите программу, вводящую последовательность целых чисел, и печатающую максимальное число идущих подряд одинаковых элементов.
Задача 5.30. Напишите программу, вводящую последовательность целых чисел, и печатающую номера первого и последнего ее максимальных элементов.
Задача 5.31. Напишите программу, вводящую последовательность целых чисел, и печатающую номер первого элемента, равного нулю, и нуль при отсутствии такого элемента в последовательности.
Задача 5.32. Напишите программу, вводящую последовательность целых чисел, и печатающую число элементов, больших предыдущего (первый элемент последовательности тоже считается таким).
Задача 5.33. Напишите программу, вводящую фразу русского языка (с использованием метода inputChars ), которая определяет, является ли введенная фраза палиндромом.
Указание Палиндром — эта фраза, инвертирование которой не изменяет ее. При этом все пробелы во фразе игнорируются.