Как не зарекурситься в
рекурсии 

и

найти иголку в стоге сена
Рассмотрим, что такое 

рекурсия, ее виды,

как осуществить поиск в массиве
Что такое рекурсия?
Рекурсия это
– замкнутый круг, мы обречены на повторение тех же
действий, но с той разницей, что входные данный можно
менять!
Рекурсия без шуточек
Рекурсия это решение задачи с помощью решения ее
маленьких подзадач, структура которых повторяет
структуру задачи. 



Пример: вычисление факториала

0! = 1

1! = 1 =1 ⋅ 1 = 1 ⋅ 0!

2! = 2 = 2 ⋅ 1 ⋅ 1 = 2 ⋅ 1!

3! = 6 = 3 ⋅ 2 ⋅ 1 ⋅ 1 = 3 ⋅ 2!

4! = 24 = 4 ⋅ 3 ⋅ 2 ⋅ 1 ⋅ 1 = 4 ⋅ 3!

На практике это выглядит как вызов методом самого же
себя, но с другими параметрами.
Модель рекурсии
Основные
характеристики рекурсии
1. Терминальная ветвь - часть метода или метод с
условием, которое прервет цепочку рекурсивных
вызовов и возвратит правильный результат. 

Должна быть в каждой рекурсии минимум одна и
достижима за конечное число рекурсивных вызовов.

2. Глубина рекурсии - количество раз вызова
функцией себя же или аналогичной.
Число Эйлера
e  ≈ 2,71828



Константу впервые вычислил швейцарский математик Якоб Бернулли в
ходе решения задачи о предельной величине процентного дохода. 

Если исходная сумма $1 и начисляется 100% годовых один раз в конце
года, то итоговая сумма будет $2. 

А если такой же процент разбить на несколько начислений, то
результирующий доход можно представить следующим образом:
Рекурсия в банке
Начисляется
100% на $1
Количество
начислений
за год
Начисляем ту же
прибыль несколько
раз в год
Результирующая
сумма
Начисляем в
конце года 100%
1 $1 * 200% = $1 * 2 = $2 $2
100% разбиты на
2 увеличения
2
$1 * 150% ^2 = $1 *
1.5^2 = $2.25
$2.25
100% разбиты на
квартальные
увеличения
4 $2.44
Начисляем так
часто, как клиент
пожелает
n ≈ $2.71828
Еще раз о факториале
• Смысл факториала - определить количество
перестановок или упорядочиваний множества из 

n элементов.



Пример: n = 3, а именно A B C

1) A B C

2) A C B

3) B A C 3! =1 * 2 * 3 = 6

4) B C A

5) С A B

6) C B A
Факториал через цикл
public class Factorial {
public static void main(String[] args) {
int result = factorialCycle(3);
System.out.println(result);
}
private static int factorialCycle(int n) {
int factorial = 1;
for (int i = 1; i <= n; i++) {
factorial *= i;
}
return factorial;
}
}
Факториал через
рекурсию
public class Factorial {
public static void main(String[] args) {
int result = factorialRecursion(2);
System.out.println(result);
}
private static int factorialRecursion(int n) {
if (n > 1) {
return n * factorialRecursion(n - 1);
}
return 1;
}
}
Параллельная рекурсия
• Несколько функций вычисляются 

и параллельно и рекурсивно. 



Пример: числа Фибоначчи

Каждое следующее число равно сумме 2х предыдущих





Происхождение: Фибоначчи рассматривает развитие
идеализированной (биологически нереальной) популяции
кроликов, предполагая, что: изначально есть новорожденная
пара кроликов (самец и самка); со второго месяца после
своего рождения кролики начинают спариваться и каждый
месяц производить новую пару кроликов; кролики никогда
не умирают. Сколько пар кроликов будет через год?
Числа Фибоначчи
public class FibonachiNumbers {
public static void main(String[] args) {
int n = 6;
int result = fibonachi(n);
System.out.println(result);
}
private static int fibonachi(int n) {
//1, 1, 2, 3, 5, 8
if (n > 2){
return fibonachi(n - 1) + fibonachi(n - 2);
}
return 1;
}
}
Хвостовая рекурсия
• Хвостовая рекурсия — частный случай рекурсии,
при котором любой рекурсивный вызов является
последней операцией перед возвратом из функции.
Всегда легко может быть заменен на итерацию.
Еще пример рекурсии
• Способ хранения данных: связный список





• Множественная рекурсия (вызов не только одной
рекурсивной функции) - обход дерева в глубину

• Непрямая рекурсия - 2 зеркала напротив друг-друга,
класс А обращается к классу В, который вызывает
класс А.



За и против рекурсии,
выводы
✓Запись алгоритма может выглядеть проще, нагляднее и
понятнее



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

๏ Используйте рекурсию для программ, где не будет
возникать слишком большой глубины рекурсии и
желательно для изначально рекурсивных алгоритмов.
Поиск
Находим иголку и не только ее
Как можно искать:

Линейный поиск
Как работает: Перебор в лоб. 



Главный плюс - понятно, как работает. 

Не надо заранее готовить данные 



Главный минус - медленно.



Особенность: в случае повторяемых значений найдет
первое
Линейный поиск
public static void main(String[] args) {
int[] arr = {1, 15, 8, 2, 15, 19}; // где ищем
int x = 8; // что ищем
int i = linearSearch(arr, x);
System.out.println(i);
}
public static int linearSearch(int[] arr, int x){
for (int i = 0; i < arr.length; i++) {
int element = arr[i];
if (element == x){
return i;
}
}
return -1;
}
Как лучше искать:

бинарный поиск
Как работает: сравнивает серединный элемент
отсортированного массива со значением, которое ищет.
Ориентируясь, где может находится нужное значение, берет
нужную часть и повторяет те же действия пока не найдет.
Или вернет ближайший индекс с минусом в случае
отсутствия элемента.



Плюс в скорости, трудоемкость 

Минус в необходимости подготовить данные, что тоже
имеет трудоемкость.

Особенность: в случае повторяемых значений найдет
непонятное
Представим бинарный поиск
в виде красно-черного дерева
Реализация бинарного
поиска
public class BinarySearch {
/**
* ищем индекс элемента в массиве
* или возвращаем -1, если элемента нету
*/
public static void main(String[] args) {
int[] arr = {1, 5, 8, 12, 15, 19}; // где ищем
int x = 15; // что ищем
int i = binarySearch(arr, x, 0, arr.length - 1);
System.out.println(i);
}
public static int binarySearch(int[] arr, int x, int low, int high) {
if (high < low) {
return -1; //не найдено
}
int mid = (low + high) / 2;
if (arr[mid] > x) {
//ищем в нижней части массива
return binarySearch(arr, x, low, mid - 1);
} else if (arr[mid] < x) {
//ищем в верхней части массива
return binarySearch(arr, x, mid + 1, high);
} else return mid; //найденный элемент
}
}
• Дерево является основой для хранения некоторых
структур данных, например дерева рода и для других
задач, где важен порядок элементов и их место, т. к.
какой соцгруппе первой давать субсидию.

• В некоторых языках программирования дерево -
основа ассоциативного массива (мапы), позволяющего
хранить пары вида «(ключ, значение)» и
поддерживающий операции добавления пары, а также
поиска и удаления пары по ключу. В стандартной
библиотеке STL языка С++ контейнер map реализован
на основе красно-чёрного дерева.
Зачем нужны деревья?
Поиск по хешу
• Хеш-функция - некая функция, которая на основе значения
элемента строит число. Для разных элементов число
должно быть разным, а для одинаковых - одинаковым.



Создана с целью упорядочивания элементов в массиве
данных, для ускорения поиска, ведь сравнивать числа
легко. Альтернатива дереву.



Хэш-таблицы плохи тем, что на их основе нельзя
реализовать быстро работающие дополнительные операции
MIN, MAX и алгоритм обхода всех хранимых пар в порядке
возрастания или убывания ключей.

Поиск в ширину
• Это обход по узлам дерева в
зависимости от их уровня. 



Пример: поиск, сколько тегов/узлов
«hotel» имеется в xml документе.
Поиск в глубину
• Представляет собой обход
дерева по всей ветке до
последнего листочка, только
потом переход на следующую
ветку/подветку



Пример: Обход лабиринта.
Как работает поисковик?
1. При появлении нового ресурса она добавляется в
базу и ей приваривается поисковой индекс.

2. Странице присваивается ранг/аппетитность.

3. При вводе поискового запроса используется
словарь похожих терминов и с помощью индексов
поисковик предлагает результаты.



http://lmgtfy.com/?q=how+search+engine+works
Как меня найти
• Facebook: https://www.facebook.com/
olexandra.dmytrenko

• Twitter: https://twitter.com/LadyInIT

• Google+: https://plus.google.com/
104080342212951796546

• Linkedin: https://www.linkedin.com/in/olexandra-
dmytrenko-078a0330/
Буду рада ответить
на вопросы :)

Рекурсия. Поиск

  • 1.
    Как не зарекурситьсяв рекурсии 
 и
 найти иголку в стоге сена Рассмотрим, что такое 
 рекурсия, ее виды, как осуществить поиск в массиве
  • 2.
  • 3.
    Рекурсия это – замкнутыйкруг, мы обречены на повторение тех же действий, но с той разницей, что входные данный можно менять!
  • 4.
    Рекурсия без шуточек Рекурсияэто решение задачи с помощью решения ее маленьких подзадач, структура которых повторяет структуру задачи. 
 
 Пример: вычисление факториала
 0! = 1
 1! = 1 =1 ⋅ 1 = 1 ⋅ 0!
 2! = 2 = 2 ⋅ 1 ⋅ 1 = 2 ⋅ 1!
 3! = 6 = 3 ⋅ 2 ⋅ 1 ⋅ 1 = 3 ⋅ 2!
 4! = 24 = 4 ⋅ 3 ⋅ 2 ⋅ 1 ⋅ 1 = 4 ⋅ 3! На практике это выглядит как вызов методом самого же себя, но с другими параметрами.
  • 5.
  • 6.
    Основные характеристики рекурсии 1. Терминальнаяветвь - часть метода или метод с условием, которое прервет цепочку рекурсивных вызовов и возвратит правильный результат. 
 Должна быть в каждой рекурсии минимум одна и достижима за конечное число рекурсивных вызовов. 2. Глубина рекурсии - количество раз вызова функцией себя же или аналогичной.
  • 7.
    Число Эйлера e  ≈2,71828
 
 Константу впервые вычислил швейцарский математик Якоб Бернулли в ходе решения задачи о предельной величине процентного дохода. Если исходная сумма $1 и начисляется 100% годовых один раз в конце года, то итоговая сумма будет $2. А если такой же процент разбить на несколько начислений, то результирующий доход можно представить следующим образом:
  • 8.
    Рекурсия в банке Начисляется 100%на $1 Количество начислений за год Начисляем ту же прибыль несколько раз в год Результирующая сумма Начисляем в конце года 100% 1 $1 * 200% = $1 * 2 = $2 $2 100% разбиты на 2 увеличения 2 $1 * 150% ^2 = $1 * 1.5^2 = $2.25 $2.25 100% разбиты на квартальные увеличения 4 $2.44 Начисляем так часто, как клиент пожелает n ≈ $2.71828
  • 9.
    Еще раз офакториале • Смысл факториала - определить количество перестановок или упорядочиваний множества из 
 n элементов.
 
 Пример: n = 3, а именно A B C
 1) A B C
 2) A C B
 3) B A C 3! =1 * 2 * 3 = 6
 4) B C A
 5) С A B
 6) C B A
  • 10.
    Факториал через цикл publicclass Factorial { public static void main(String[] args) { int result = factorialCycle(3); System.out.println(result); } private static int factorialCycle(int n) { int factorial = 1; for (int i = 1; i <= n; i++) { factorial *= i; } return factorial; } }
  • 11.
    Факториал через рекурсию public classFactorial { public static void main(String[] args) { int result = factorialRecursion(2); System.out.println(result); } private static int factorialRecursion(int n) { if (n > 1) { return n * factorialRecursion(n - 1); } return 1; } }
  • 12.
    Параллельная рекурсия • Несколькофункций вычисляются 
 и параллельно и рекурсивно. 
 
 Пример: числа Фибоначчи
 Каждое следующее число равно сумме 2х предыдущих
 
 
 Происхождение: Фибоначчи рассматривает развитие идеализированной (биологически нереальной) популяции кроликов, предполагая, что: изначально есть новорожденная пара кроликов (самец и самка); со второго месяца после своего рождения кролики начинают спариваться и каждый месяц производить новую пару кроликов; кролики никогда не умирают. Сколько пар кроликов будет через год?
  • 13.
    Числа Фибоначчи public classFibonachiNumbers { public static void main(String[] args) { int n = 6; int result = fibonachi(n); System.out.println(result); } private static int fibonachi(int n) { //1, 1, 2, 3, 5, 8 if (n > 2){ return fibonachi(n - 1) + fibonachi(n - 2); } return 1; } }
  • 14.
    Хвостовая рекурсия • Хвостоваярекурсия — частный случай рекурсии, при котором любой рекурсивный вызов является последней операцией перед возвратом из функции. Всегда легко может быть заменен на итерацию.
  • 15.
    Еще пример рекурсии •Способ хранения данных: связный список
 
 
 • Множественная рекурсия (вызов не только одной рекурсивной функции) - обход дерева в глубину • Непрямая рекурсия - 2 зеркала напротив друг-друга, класс А обращается к классу В, который вызывает класс А.
 

  • 16.
    За и противрекурсии, выводы ✓Запись алгоритма может выглядеть проще, нагляднее и понятнее
 
 - Чревато загромождением памяти, ведь надо помнить все предыдущие действия, чтоб идти по рекурсии. ๏ Используйте рекурсию для программ, где не будет возникать слишком большой глубины рекурсии и желательно для изначально рекурсивных алгоритмов.
  • 17.
  • 18.
    Как можно искать:
 Линейныйпоиск Как работает: Перебор в лоб. 
 
 Главный плюс - понятно, как работает. 
 Не надо заранее готовить данные 
 
 Главный минус - медленно.
 
 Особенность: в случае повторяемых значений найдет первое
  • 19.
    Линейный поиск public staticvoid main(String[] args) { int[] arr = {1, 15, 8, 2, 15, 19}; // где ищем int x = 8; // что ищем int i = linearSearch(arr, x); System.out.println(i); } public static int linearSearch(int[] arr, int x){ for (int i = 0; i < arr.length; i++) { int element = arr[i]; if (element == x){ return i; } } return -1; }
  • 20.
    Как лучше искать:
 бинарныйпоиск Как работает: сравнивает серединный элемент отсортированного массива со значением, которое ищет. Ориентируясь, где может находится нужное значение, берет нужную часть и повторяет те же действия пока не найдет. Или вернет ближайший индекс с минусом в случае отсутствия элемента.
 
 Плюс в скорости, трудоемкость Минус в необходимости подготовить данные, что тоже имеет трудоемкость. Особенность: в случае повторяемых значений найдет непонятное
  • 21.
    Представим бинарный поиск ввиде красно-черного дерева
  • 22.
    Реализация бинарного поиска public classBinarySearch { /** * ищем индекс элемента в массиве * или возвращаем -1, если элемента нету */ public static void main(String[] args) { int[] arr = {1, 5, 8, 12, 15, 19}; // где ищем int x = 15; // что ищем int i = binarySearch(arr, x, 0, arr.length - 1); System.out.println(i); } public static int binarySearch(int[] arr, int x, int low, int high) { if (high < low) { return -1; //не найдено } int mid = (low + high) / 2; if (arr[mid] > x) { //ищем в нижней части массива return binarySearch(arr, x, low, mid - 1); } else if (arr[mid] < x) { //ищем в верхней части массива return binarySearch(arr, x, mid + 1, high); } else return mid; //найденный элемент } }
  • 23.
    • Дерево являетсяосновой для хранения некоторых структур данных, например дерева рода и для других задач, где важен порядок элементов и их место, т. к. какой соцгруппе первой давать субсидию. • В некоторых языках программирования дерево - основа ассоциативного массива (мапы), позволяющего хранить пары вида «(ключ, значение)» и поддерживающий операции добавления пары, а также поиска и удаления пары по ключу. В стандартной библиотеке STL языка С++ контейнер map реализован на основе красно-чёрного дерева. Зачем нужны деревья?
  • 24.
    Поиск по хешу •Хеш-функция - некая функция, которая на основе значения элемента строит число. Для разных элементов число должно быть разным, а для одинаковых - одинаковым.
 
 Создана с целью упорядочивания элементов в массиве данных, для ускорения поиска, ведь сравнивать числа легко. Альтернатива дереву.
 
 Хэш-таблицы плохи тем, что на их основе нельзя реализовать быстро работающие дополнительные операции MIN, MAX и алгоритм обхода всех хранимых пар в порядке возрастания или убывания ключей.

  • 25.
    Поиск в ширину •Это обход по узлам дерева в зависимости от их уровня. 
 
 Пример: поиск, сколько тегов/узлов «hotel» имеется в xml документе.
  • 26.
    Поиск в глубину •Представляет собой обход дерева по всей ветке до последнего листочка, только потом переход на следующую ветку/подветку
 
 Пример: Обход лабиринта.
  • 27.
    Как работает поисковик? 1.При появлении нового ресурса она добавляется в базу и ей приваривается поисковой индекс. 2. Странице присваивается ранг/аппетитность. 3. При вводе поискового запроса используется словарь похожих терминов и с помощью индексов поисковик предлагает результаты.
 
 http://lmgtfy.com/?q=how+search+engine+works
  • 28.
    Как меня найти •Facebook: https://www.facebook.com/ olexandra.dmytrenko • Twitter: https://twitter.com/LadyInIT • Google+: https://plus.google.com/ 104080342212951796546 • Linkedin: https://www.linkedin.com/in/olexandra- dmytrenko-078a0330/
  • 29.