Вы находитесь на странице: 1из 1

телефон: +(38) 063-048-7663 | Email: GolovachCourses@gmail.

com | Skype: GolovachCourses

Учебно-информационный сайт.

Курс ЯЗЫК JAVA Курс WEB РАЗРАБОТКА Курс БАЗЫ ДАННЫХ Успеваемость Процесс обучения Тестирование

Контакты

Лекция 2.2: Базовые алгоритмы / Рекурсия.

1. Прямая рекурсия без ветвления Приветствуем, pafnat


….1.1 Простой пример
….1.2 Факториал: итеративное вычисление Настройки профиля
….1.3 Факториал: рекурсивное вычисление Выйти
2. Косвенная рекурсия без ветвления
….2.1 Вычисление четности/нечетности числа
….2.2 Преобразование в строку (Object/Object[]) Ваша успеваемость
3. Прямая рекурсия c ветвлениями
….3.1 Функция Фибоначчи: итеративное вычисление Java Core 14.34%
….3.2 Функция Фибоначчи: рекурсивное вычисление 1. Основы Java 88.07%
4. Косвенная рекурсия c ветвлениями 2. Базовые алгоритмы 24.13%
5. Другие виды рекурсии 3. Исключения 31.21%
Тесты по всей лекции 4. Ввод/вывод 0%
Видео 5. Многопоточность 0%
Лабораторные 6. Коллекции 0%
….proc.recursion.hanoi_tower 7. ООП: Синтаксис 0%
….proc.recursion.permutation 8. ООП: Шаблоны 0%
….proc.recursion.parser 9. Продвинутые 0%
Литература возможности
10. Java 8 0%

1. Прямая рекурсия без ветвления


РАЗДЕЛ НАХОДИТСЯ В РАЗРАБОТКЕ

Рекурсия бывает:
- прямая и косвенная
- без ветвления и с ветвлением

1.1 Простой пример


РАЗДЕЛ НАХОДИТСЯ В РАЗРАБОТКЕ

Рассмотрим несколько примеров прямой рекурсии без ветвления.


Печатаем “на входе” (прямой порядок):

1 public class App { ?


2 public static void main(String[] args) {
3 f(1);
4 }
5
6 public static void f(int arg) {
7 System.out.print(" " + arg);
8 if (arg < 7) {
9 f(2 * arg);
10 }
11 }
12 }
13
14 >> 1 2 4 8

Печатаем “на выходе” (обратный порядок):

1 public class App { ?


2 public static void main(String[] args) {
3 f(1);
4 }
5
6 public static void f(int arg) {
7 if (arg < 7) {
8 f(2 * arg);
9 }
10 System.out.print(" " + arg);
11 }
12 }
13
14 >> 8 4 2 1

Печатаем и “на входе” и “на выходе”:

1 public class App { ?


2 public static void main(String[] args) {
3 f(1);
4 }
5
6 public static void f(int arg) {
7 System.out.print(" " + arg);
8 if (arg < 7) {
9 f(2 * arg);
10 }
11 System.out.print(" " + arg);
12 }
13 }
14
15 >> 1 2 4 8 8 4 2 1

Тест
Для прохождения теста по теме recursion (уровень сложности теста: simple) нажмите “Start Quiz”

1.2 Факториал: итеративное вычисление


РАЗДЕЛ НАХОДИТСЯ В РАЗРАБОТКЕ

Факториал – это функция целочисленного положительного аргумента, которая возвращает целое число равное
произведению всех целых чисел от 1 до аргумента.
Пример:
factorial(5) = 1 * 2 * 3 * 4 * 5 = 120

1 public class App { ?


2 public static void main(String[] args) {
3 System.out.println(factorial(5));
4 }
5
6 public static int factorial(int arg) {
7 int result = 1;
8 for (int k = 1; k <= arg; k++) {
9 result *= k;
10 }
11 return result;
12 }
13 }
14
15 >> 120

Для больших значений можно столкнуться с переполнением int:

1 public class App { ?


2 public static void main(String[] args) {
3 System.out.println(factorial(17));
4 }
5
6 public static int factorial(int arg) {
7 int result = 1;
8 for (int k = 1; k <= arg; k++) {
9 result *= k;
10 }
11 return result;
12 }
13 }
14
15 >> -288522240

Факториал растет очень быстро, возможно, стоит использовать не примитивные типы, а BigInteger:

1 import java.math.BigInteger; ?
2
3 public class App {
4 public static void main(String[] args) {
5 System.out.println(factorial(40));
6 }
7
8 public static BigInteger factorial(int arg) {
9 BigInteger result = BigInteger.ONE;
10 for (int k = 1; k <= arg; k++) {
11 result = result.multiply(BigInteger.valueOf(k));
12 }
13 return result;
14 }
15 }
16
17 >> 815915283247897734345611269596115894272000000000

1.3 Факториал: рекурсивное вычисление


РАЗДЕЛ НАХОДИТСЯ В РАЗРАБОТКЕ

Однако, для расчет факториала можно делать и рекурсивно:

1 public class App { ?


2 public static void main(String[] args) {
3 System.out.println(factorial(5));
4 }
5
6 public static int factorial(int arg) {
7 if (arg == 1) {
8 return 1;
9 } else {
10 return arg * factorial(arg - 1);
11 }
12 }
13 }
14
15 >> 120

Или же с использованием тернарного условного оператора даже короче (хотя и загадочнее):

1 public class App { ?


2 public static void main(String[] args) {
3 System.out.println(factorial(5));
4 }
5
6 public static int factorial(int arg) {
7 return (arg == 1) ? 1 : arg * factorial(arg - 1);
8 }
9 }
10
11 >> 120

Тест
Для прохождения теста по теме Proc.Recursion.Ariphmetic (уровень сложности теста: mid) нажмите “Start Quiz”

2. Косвенная рекурсия без ветвления


РАЗДЕЛ НАХОДИТСЯ В РАЗРАБОТКЕ

2.1 Вычисление четности/нечетности числа


РАЗДЕЛ НАХОДИТСЯ В РАЗРАБОТКЕ

Пример #1: вычисление четности (isEven) и нечетности (isOdd) числа.


Мы знаем, что 0 – четное число и НЕ НЕчетное число. Для чисел больше нуля – переходим к аргументу меньшему
на 1

1 public class App { ?


2 public static void main(String[] args) {
3 System.out.println("10 - нечетное число: " + isOdd(10));
4 System.out.println("10 - четное число: " + isEven(10));
5 }
6
7 // проверка на четность
8 public static boolean isEven(int k) {
9 if (k == 0) {
10 return true; // 0 - четное число
11 } else {
12 return isOdd(k - 1);
13 }
14 }
15
16 // проверка на НЕчетность
17 public static boolean isOdd(int k) {
18 if (k == 0) {
19 return false; // 0 - НЕ НЕчетное число
20 } else {
21 return isEven(k - 1);
22 }
23 }
24 }
25
26 >> 10 - нечетное число: false
27 >> 10 - четное число: true

2.2 Преобразование в строку (Object/Object[])


РАЗДЕЛ НАХОДИТСЯ В РАЗРАБОТКЕ

Пример #2:
Если toStrObj(Object) обнаруживает, что ее аргумент – массив, то вызывает toStrArr(Object[]).
А toStrArr(Object[]) для каждого аргумента вызывает toStrObj(Object).

1 public class App { ?


2 public static void main(String[] args) {
3 System.out.println(toStrObj(42));
4 System.out.println(toStrObj(new Object[] {
5 "Hello",
6 42}));
7 System.out.println(toStrObj(new Object[] {
8 "Hello",
9 42,
10 new Object[] {
11 "Hello",
12 42,
13 new Object[] {
14 "Hello",
15 42,
16 new Object[0]}}}));
17 }
18
19 public static String toStrObj(Object arg) {
20 if (arg.getClass().isArray()) {
21 return toStrArr((Object[]) arg);
22 } else {
23 return arg.toString();
24 }
25 }
26
27 public static String toStrArr(Object[] array) {
28 String result = "[";
29 for (int k = 0; k < array.length; k++) {
30 result += toStrObj(array[k]);
31 if (k < array.length - 1) {
32 result += ", ";
33 }
34 }
35 return result + "]";
36 }
37 }
38
39 >> 42
40 >> [Hello, 42]
41 >> [Hello, 42, [Hello, 42, [Hello, 42, []]]]

Тест
Для прохождения теста по теме Proc.Recursion.Indirect (уровень сложности теста: mid) нажмите “Start Quiz”

3. Прямая рекурсия c ветвлениями


РАЗДЕЛ НАХОДИТСЯ В РАЗРАБОТКЕ

Рассмотрим функцию Фибоначчи, определяемую следующим образом:


fib(0) = 1
fib(1) = 1
fib(2) = fib(0) + fib(1)
fib(3) = fib(1) + fib(2)
fib(4) = fib(2) + fib(3)

Вот значения функции Фибоначчи от аргументов 0, 1 … 10

1 ------------------------------------------------------- ?
2 | arg | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10|
3 -------------------------------------------------------
4 | fib(arg)| 1 | 1 | 2 | 3 | 5 | 8 | 13| 21| 34| 55| 89|
5 -------------------------------------------------------

3.1 Функция Фибоначчи: итеративное вычисление


РАЗДЕЛ НАХОДИТСЯ В РАЗРАБОТКЕ

Эту функцию можно вычислять итеративно (int[] result – это “память”, в которой хранятся значения вычисленные
на предыдущих шагах):

1 public class App { ?


2 public static void main(String[] args) {
3 for (int k = 0; k < 10; k++) {
4 System.out.println("fib(" + k + ") = " + fib(k));
5 }
6 }
7
8 public static int fib(int arg) {
9 if (arg == 0)
10 return 1;
11 if (arg == 1)
12 return 1;
13 int[] result = new int[arg + 1];
14 result[0] = 1;
15 result[1] = 1;
16 for (int k = 2; k < result.length; k++) {
17 result[k] = result[k - 2] + result[k - 1];
18 }
19 return result[arg];
20 }
21 }
22
23 >> fib(0) = 1
24 >> fib(1) = 1
25 >> fib(2) = 2
26 >> fib(3) = 3
27 >> fib(4) = 5
28 >> fib(5) = 8
29 >> fib(6) = 13
30 >> fib(7) = 21
31 >> fib(8) = 34
32 >> fib(9) = 55

Можно эти значения не запоминать, а хранить только последние два значения и через них вычислять следующее
(используем идиому обмена значениями через дополнительную переменную)

1 public class App { ?


2 public static void main(String[] args) {
3 for (int k = 0; k < 10; k++) {
4 System.out.println("fib(" + k + ") = " + fib(k));
5 }
6 }
7
8 public static int fib(int arg) {
9 if (arg < 2) {
10 return 1;
11 } else {
12 int prev = 1;
13 int next = 1;
14 for (int k = 2; k <= arg; k++) {
15 int tmp = prev;
16 prev = next;
17 next = next + tmp;
18 }
19 return next;
20 }
21 }
22 }
23
24 >> fib(0) = 1
25 >> fib(1) = 1
26 >> fib(2) = 2
27 >> fib(3) = 3
28 >> fib(4) = 5
29 >> fib(5) = 8
30 >> fib(6) = 13
31 >> fib(7) = 21
32 >> fib(8) = 34
33 >> fib(9) = 55

Можно свести даже до такой формы (используя идиому обмена значениями без дополнительной переменной)

1 public class App { ?


2 public static void main(String[] args) {
3 for (int k = 0; k < 10; k++) {
4 System.out.println("fib(" + k + ") = " + fib(k));
5 }
6 }
7
8 public static int fib(int arg) {
9 if (arg < 2) {
10 return 1;
11 } else {
12 int prev = 1, next = 1;
13 for (int k = 2; k <= arg; k++) {
14 next = next + prev;
15 prev = next - prev;
16 }
17 return next;
18 }
19 }
20 }
21
22 >> fib(0) = 1
23 >> fib(1) = 1
24 >> fib(2) = 2
25 >> fib(3) = 3
26 >> fib(4) = 5
27 >> fib(5) = 8
28 >> fib(6) = 13
29 >> fib(7) = 21
30 >> fib(8) = 34
31 >> fib(9) = 55

3.2 Функция Фибоначчи: рекурсивное вычисление


РАЗДЕЛ НАХОДИТСЯ В РАЗРАБОТКЕ

Однако мы можем вычислить эту функцию и рекурсивно

1 public class App { ?


2 public static void main(String[] args) {
3 for (int k = 0; k < 10; k++) {
4 System.out.println("fib(" + k + ") = " + fib(k));
5 }
6 }
7
8 public static int fib(int arg) {
9 if (arg == 0) {
10 return 1;
11 } else if (arg == 1) {
12 return 1;
13 } else {
14 return fib(arg - 2) + fib(arg - 1);
15 }
16 }
17 }
18
19 >> fib(0) = 1
20 >> fib(1) = 1
21 >> fib(2) = 2
22 >> fib(3) = 3
23 >> fib(4) = 5
24 >> fib(5) = 8
25 >> fib(6) = 13
26 >> fib(7) = 21
27 >> fib(8) = 34
28 >> fib(9) = 55

Или даже в еще более короткой форме – в одну строчку

1 public class App { ?


2 public static void main(String[] args) {
3 for (int k = 0; k < 10; k++) {
4 System.out.println("fib(" + k + ") = " + fib(k));
5 }
6 }
7
8 public static int fib(int arg) {
9 return arg < 2 ? 1 : fib(arg - 2) + fib(arg - 1);
10 }
11 }
12
13 >> fib(0) = 1
14 >> fib(1) = 1
15 >> fib(2) = 2
16 >> fib(3) = 3
17 >> fib(4) = 5
18 >> fib(5) = 8
19 >> fib(6) = 13
20 >> fib(7) = 21
21 >> fib(8) = 34
22 >> fib(9) = 55

Вы действительно поняли рекурсию, если можете без запуска программы сказать, что выведут следующие
программы

1 public class App { ?


2 public static void main(String[] args) {
3 fib(5);
4 }
5
6 public static int fib(int arg) {
7 System.out.print(" " + arg);
8 return arg < 2 ? 1 : fib(arg - 2) + fib(arg - 1);
9 }
10 }
11
12 >> 5 3 1 2 0 1 4 2 0 1 3 1 2 0 1

1 public class App { ?


2 public static void main(String[] args) {
3 fib(5);
4 }
5
6 public static int fib(int arg) {
7 int result = arg < 2 ? 1 : fib(arg - 2) + fib(arg - 1);
8 System.out.print(" " + arg);
9 return result;
10 }
11 }
12
13 >> 1 0 1 2 3 0 1 2 1 0 1 2 3 4 5

1 public class App { ?


2 public static void main(String[] args) {
3 fib(5);
4 }
5
6 public static int fib(int arg) {
7 return arg < 2 ? 1 : fib(arg - 2) + _(arg) + fib(arg - 1);
8 }
9
10 public static int _(int arg) {
11 System.out.print(" " + arg);
12 return 0;
13 }
14 }
15
16 >> 3 2 5 2 4 3 2

В данном случае мы обходим дерево в глубину слева-направо

1 5 ?
2 / \
3 / \
4 3 4
5 /\ / \
6 1 2 2 3
7 /\ /\ /\
8 0 1 0 1 1 2
9 /\
10 0 1

Если же мы заменим fib(k) = fib(k-2) + fib(k-1) на fib(k) = fib(k-1) + fib(k-2), то РЕЗУЛЬТАТ вычисления функции не
изменится, однако ПРОЦЕСС будет другой (обход ЗЕРКАЛЬНОГО по отношению к предыдущему дерева в
глубину слева-направо)

1 public class App { ?


2 public static void main(String[] args) {
3 fib(5);
4 }
5
6 public static int fib(int arg) {
7 System.out.print(" " + arg);
8 return arg < 2 ? 1 : fib(arg - 1) + fib(arg - 2);
9 }
10 }
11
12 >> 5 4 3 2 1 0 1 2 1 0 3 2 1 0 1

Обходим теперь вот такое дерево

1 5 ?
2 / \
3 / \
4 4 3
5 / \ / \
6 3 2 2 1
7 /\ /\ /\
8 2 1 1 0 1 0
9 /\
10 1 0

Тест
Для прохождения теста по теме recursion.fibonacci нажмите “Start Quiz”

4. Косвенная рекурсия c ветвлениями


РАЗДЕЛ НАХОДИТСЯ В РАЗРАБОТКЕ

5. Другие виды рекурсии


РАЗДЕЛ НАХОДИТСЯ В РАЗРАБОТКЕ

Тесты по всей лекции


Тест, состоящий из случайных вопросов тестов этой лекции

Для прохождения теста нажмите “Start Quiz”

Видео
Набор декабрь 2013
Набор октябрь 2013 (РЕКОМЕНДУЕМОЕ)
Набор июль 2013
Набор апрель 2013
Набор февраль 2013
Набор январь 2013
Набор октябрь 2012

Лабораторные
Лабораторная: proc.recursion.hanoi_tower

proc.recursion.hanoi_tower
Проставьте правильные аргументы методов в рекурсивных вызовах exchange вместо вопросительных знаков.
Итоговый код должен корректно решать задачу о Ханойской башне.
Решение должно иметь вид

public static void exchange(


Stack from, Stack help,
Stack to, int count) {
if (count > 0) {
exchange(?, ?, ?, ?);
int biggest = from.pop();
to.push(biggest);
exchange(?, ?, ?, ?);
}
}

import java.util.Stack;

public class HanoiSolver {


public static void exchange(Stack from, Stack help, Stack to, int count) {

}
}

Лабораторная: proc.recursion.permutation

proc.recursion.permutation
Задача о генерации всех возможных перестановок элементов заданного списка.
Из списка длины N можно построить N! возможных перестановок (N! = 1 * 2 * … * (N – 1) * N, 1!=1, 2!=1*2=2,
3!=1*2*3=6, 4!=1*2*3*4=24, …).
Пример:
Из элементов списка [10, 20, 30] можно построить 6 различных перестановок:
[20, 30, 20]
[10, 20, 30]
[30, 20, 10]
[20, 10, 30]
[30, 10, 20]
[10, 30, 20]

Схема рекурсивного решения:


Все возможные перестановки N элементов ([a(1), a(2), a(3), ..., a(N)]) распадаются на N непересекающихся
множеств:
1) те, что начинаются с a(1)
2) те, что начинаются с a(2)
3) те, что начинаются с a(3)

N) те, что начинаются с a(N)
При этом множество перестановок начинающихся с a(K) (для К = 1,2,3,…N) можно построить следующим образом:
1) первым элементов поставим a(K)
2) все остальные позиции занимают всевозможные перестановки оставшихся элементов [a(1), a(2), ..., a(K-1),
a(K+1), ..., a(N-1), a(N)]

Вот графическая схема решения для списка [10, 20, 30]

| -> [10, 20, ??] -> | -> [10, 20, 30]


| -> [10, ??, ??] -> |
| | -> [10, 30, ??] -> | -> [10, 30, 20]
|
| | -> [20, 10, ??] -> | -> [20, 10, 30]
[??, ??, ??] -> | -> [20, ??, ??] -> |
| | -> [20, 30, ??] -> | -> [20, 30, 10]
|
| | -> [30, 10, ??] -> | -> [30, 10, 20]
| -> [30, ??, ??] -> |
| -> [30, 20, ??] -> | -> [30, 20, 10]

Которая приводит к множеству перестановок:


[10, 20, 30]
[10, 30, 20]
[20, 10, 30]
[20, 30, 20]
[30, 10, 20]
[30, 20, 10]

Как это работает.


1. В начале стоит ИЛИ 10 ИЛИ 20 ИЛИ 30;
1.1 Если вначале стоит 10, то дальше стоит ИЛИ 20 ИЛИ 30
1.1.1 Если вначале стоит 10, и дальше стоит 20, то осталось 30
1.1.2 Если вначале стоит 10, и дальше стоит 30, то осталось 20
1.2 Если вначале стоит 20, то дальше стоит ИЛИ 10 ИЛИ 30
1.2.1 Если вначале стоит 20, и дальше стоит 10, то осталось 30
1.2.2 Если вначале стоит 20, и дальше стоит 30, то осталось 10
1.3 Если вначале стоит 30, то дальше стоит ИЛИ 10 ИЛИ 20
1.3.1 Если вначале стоит 30, и дальше стоит 10, то осталось 20
1.3.2 Если вначале стоит 30, и дальше стоит 20, то осталось 10

Это некорректный код, который должен рекурсивно строить все возможные перестановки.
Исправьте его.

import java.util.Arrays;

public class Permutator {


public static void main(String[] args) {
int[] arr = {1, 2, 3};
permutation(arr, arr.length);
}
private static void permutation(int[] arr, int size) {
if (size < 2) {
System.out.println(Arrays.toString(arr));
} else {
for (int k = 0; k < size; k++) {
swap(arr, k, size - 1);
permutation(arr, size - 1);
}
}
}
private static void swap(int[] arr, int index0, int index1) {
int tmp = arr[index0];
arr[index0] = arr[index1];
arr[index1] = tmp;
}
}

>> [2, 3, 1]
>> [2, 3, 1]
>> [1, 2, 3]
>> [1, 2, 3]
>> [2, 1, 3]
>> [2, 1, 3]

Этот код “недоперемешивает” элементы. Количество вариантов верное, но по какой-то причине имеются
дубликаты.

import java.util.ArrayList;
import java.util.List;

public class Permutator {


public static List<List<Integer>> permute(List<Integer> list, int size) {

private static void swap(List<Integer> list, int index0, int index1) {


Integer tmp = list.get(index0);
list.set(index0, list.get(index1));
list.set(index1, tmp);
}
}

Лабораторная: proc.recursion.parser

proc.recursion.parser
Это пример небольшого и ограниченного по функциональности рекурсивного парсера арифметических
выражений.
Он умеет:
1) встретив скобки с двух сторон – свести задачу к анализу содержимого скобок (пример:”(1+1)” -> “1+1″, пример
“(1+(2/3))” -> “1+(2/3)”);
2) встретив число-знак-XXX – свести задачу к анализу XXX
(пример:”1*(10-3)” -> “(10-3)”, пример “3+(2/(9+1))” -> “(2/(9+1)”);
Задание: переписать его, что бы он ВМЕСТО пункта 2 дела пункт 2′
2′) встретив XXX-знак-число – сведил задачу к анализу XXX.
(пример:”(10-3)*1″ -> “(10-3)”, пример “(2/(9+1))+3″ -> “(2/(9+1)”);
Предупреждение #1: это не полноценный парсер арифметических выражений, есть множество корректных
выражений на которых он “падает” или вычисляет некорректно (“(1+1)+(1+1)”, “-1″, …).
Предупреждение #2: в условиях лабораторной ожидается, что старые выражения вида число-знак-XXX
больше на разбираются.

public class Parser {


public static void main(String[] args) {
System.out.println(eval("123"));
System.out.println(eval("2*3"));
System.out.println(eval("2*(1+3)"));
System.out.println(eval("1+(5-2*(13/6))"));
}

private static int eval(String expr) {


return eval(expr, 0, expr.length());
}

private static int eval(String expr, int from, int to) {


if (expr.charAt(from) == '(') {
return eval(expr, from + 1, to - 1);
} else {
int pos = from;
while (pos < to) {
if (Character.isDigit(expr.charAt(pos))) {
pos++;
} else {
int leftOperand = Integer.valueOf(expr.substring(from, pos));
char operation = expr.charAt(pos);
int rightOperand = eval(expr, pos + 1, to);
switch (operation) {
case '+':
return leftOperand + rightOperand;
case '-':
return leftOperand - rightOperand;
case '*':
return leftOperand * rightOperand;
case '/':
return leftOperand / rightOperand;
}
}
}
return Integer.valueOf(expr.substring(from, to));
}
}
}

Тестирующий код (для моего примера)

public class ParserTest {


public static void main(String[] args) {
System.out.println(">> 123 = " + Parser.eval("123"));
System.out.println(">> 2*3 = " + Parser.eval("2*3"));
System.out.println(">> 2*(1+3) = " + Parser.eval("2*(1+3)"));
System.out.println(">> 1+(5-2*(13/6)) = " + Parser.eval("1+(5-2*(13/6))"));
}
}

Тестирующий код (для вашего решения)

public class ParserTest {


public static void main(String[] args) {
System.out.println(">> 123 = " + Parser.eval("123"));
System.out.println(">> 2*3 = " + Parser.eval("2*3"));
System.out.println(">> (1+3)*2 = " + Parser.eval("(1+3)*2"));
System.out.println(">> ((13/6)*2-5)+1 = " + Parser.eval("((13/6)*2-5)+1"));
}
}

Демонстрация работы метода Character.isDidit(...)

public class IsDigitDemo {


public static void main(String[] args) {
System.out.println(Character.isDigit('0'));
System.out.println(Character.isDigit('2'));
System.out.println(Character.isDigit('4'));
System.out.println(Character.isDigit('5'));
System.out.println(Character.isDigit('7'));
System.out.println(Character.isDigit('9'));
System.out.println(Character.isDigit(' '));
System.out.println(Character.isDigit('A'));
System.out.println(Character.isDigit('!'));
}
}
>> true
>> true
>> true
>> true
>> true
>> true
>> false
>> false
>> false

Демонстрация работы метода Integer.valueOf(...)

public class ValueOfDemo {


public static void main(String[] args) {
int value0 = Integer.valueOf("123");
System.out.println(value0);

int value1 = Integer.valueOf("abc");


System.out.println(value1);
}
}
>> 123
>> ... java.lang.NumberFormatException: For input string: "abc" ...

Демонстрация работы метода String.substring(...)

public class SubstringDemo {


public static void main(String[] args) {
System.out.println("Hello!".substring(0, 6));
System.out.println("Hello!".substring(0, 5));
System.out.println("Hello!".substring(0, 4));
System.out.println("Hello!".substring(0, 3));
System.out.println();
System.out.println("Hello!".substring(0, 6));
System.out.println("Hello!".substring(1, 6));
System.out.println("Hello!".substring(2, 6));
System.out.println("Hello!".substring(3, 6));
System.out.println();
System.out.println("Hello!".substring(0, 6));
System.out.println("Hello!".substring(1, 5));
System.out.println("Hello!".substring(2, 3));
}
}
>> Hello!
>> Hello
>> Hell
>> Hel
>>
>> Hello!
>> ello!
>> llo!
>> lo!
>>
>> Hello!
>> ello
>> ll

public class Parser {


public static int eval(String expr) {

}
}

Литература
Stack/Method invocation в JVM
….- JVM Spec: Java Virtual Machine Stacks
….- JVM Spec: Frames
….- JVM Spec: Local Variables
….- JVM Spec: Receiving Arguments
….- JVM Spec: Invoking Methods
Алгоритмическая сторона вопроса
- Вирт, “Алгоритмы и структуры данных”
….- глава 3, “Рекурсивные алгоритмы”
- Макконелл, “Анализ алгоритмов”
….- Глава 1.5. “Алгоритмы вида «разделяй и властвуй»”
- Кормен, “Алгоритмы. Построение и анализ”
….- Глава 4. Рекуррентные соотношения

© 2014 Golovach Courses |

Вам также может понравиться