logo

Вступ до рекурсії – Навчальні посібники зі структури даних і алгоритмів

Що таке рекурсія?
Процес, у якому функція викликає саму себе прямо чи опосередковано, називається рекурсією, а відповідна функція — рекурсивною функцією. Використовуючи рекурсивний алгоритм, певні проблеми можна вирішити досить легко. Прикладами таких проблем є Ханойські вежі (TOH) , Обхід дерева в порядку/попередньому/після замовлення , DFS Graph тощо. Рекурсивна функція вирішує певну проблему, викликаючи її копію та розв’язуючи менші підпроблеми вихідних задач. Багато інших рекурсивних викликів можуть бути створені за потреби. Важливо знати, що ми повинні надати певний регістр, щоб завершити цей процес рекурсії. Отже, ми можемо сказати, що щоразу функція викликає себе з простішою версією вихідної проблеми.

Необхідність рекурсії



Рекурсія - це дивовижна техніка, за допомогою якої ми можемо зменшити довжину нашого коду та полегшити його читання та запис. Він має певні переваги перед ітераційною технікою, про які йтиметься пізніше. Завдання, яке можна визначити за допомогою подібної підзадачі, рекурсія є одним із найкращих рішень для цього. Наприклад; Факторіал числа.

Властивості рекурсії:

  • Багаторазове виконання одних і тих самих операцій з різними вхідними даними.
  • На кожному кроці ми намагаємося робити менші внески, щоб зменшити проблему.
  • Щоб зупинити рекурсію, потрібна базова умова, інакше виникне нескінченний цикл.

Алгоритм: кроки

The algorithmic steps for implementing recursion in a function are as follows: Step1 - Define a base case: Identify the simplest case for which the solution is known or trivial. This is the stopping condition for the recursion, as it prevents the function from infinitely calling itself. Step2 - Define a recursive case: Define the problem in terms of smaller subproblems. Break the problem down into smaller versions of itself, and call the function recursively to solve each subproblem. Step3 - Ensure the recursion terminates: Make sure that the recursive function eventually reaches the base case, and does not enter an infinite loop. step4 - Combine the solutions: Combine the solutions of the subproblems to solve the original problem.>

Математична інтерпретація



Давайте розглянемо задачу, що програміст повинен визначити суму перших n натуральних чисел, є кілька способів зробити це, але найпростішим підходом є просто додати числа, починаючи з 1, до n. Отже, функція виглядає просто так,

approach(1) – просто додавання один за одним

f(n) = 1 + 2 + 3 +……..+ n



але існує інший математичний підхід до представлення цього,

approach(2) – рекурсивне додавання

f(n) = 1 n=1

f(n) = n + f(n-1) n>1

Існує проста різниця між підходом (1) і підходом (2), і це в підхід(2) функція f( ) сама викликається всередині функції, тому це явище називається рекурсією, а функція, що містить рекурсію, називається рекурсивною функцією. Зрештою, це чудовий інструмент у руках програмістів, щоб кодувати деякі проблеми набагато простіше та ефективніше спосіб.

Як рекурсивні функції зберігаються в пам'яті?

Рекурсія використовує більше пам’яті, оскільки рекурсивна функція додає стек із кожним рекурсивним викликом і зберігає там значення до завершення виклику. Рекурсивна функція використовує структуру LIFO (ОСТАННІЙ ПРИЙШОВ, ПЕРШИЙ ВИХОДИВ), як і структура стекових даних. структура стеку-даних/

Що таке базова умова в рекурсії?
У рекурсивній програмі надається розв’язок базового випадку, а розв’язок більшої проблеми виражається через менші проблеми.

int fact(int n) { if (n <= 1) // base case return 1; else return n*fact(n-1); }>

У наведеному вище прикладі визначено базовий варіант для n <= 1, і більше значення числа можна розв’язати шляхом перетворення на менше, доки не буде досягнуто базового випадку.

Як конкретна проблема вирішується за допомогою рекурсії?
Ідея полягає в тому, щоб представити проблему в термінах однієї чи кількох менших проблем і додати одну чи декілька базових умов, які зупиняють рекурсію. Наприклад, ми обчислюємо факторіал n, якщо знаємо факторіал (n-1). Базовим випадком факторіала буде n = 0. Ми повертаємо 1, коли n = 0.

Чому під час рекурсії виникає помилка переповнення стека?
Якщо базовий варіант не досягнуто або не визначено, може виникнути проблема переповнення стека. Щоб зрозуміти це, візьмемо приклад.

int fact(int n) { // wrong base case (it may cause // stack overflow). if (n == 100) return 1; else return n*fact(n-1); }>

Якщо викликається fact(10), він викликає fact(9), fact(8), fact(7) і так далі, але число ніколи не досягне 100. Отже, базовий випадок не досягнуто. Якщо ці функції в стеку вичерпують пам’ять, це спричинить помилку переповнення стеку.

Яка різниця між прямою та непрямою рекурсією?
Функція fun називається прямою рекурсією, якщо вона викликає ту саму функцію fun. Функція fun називається непрямою рекурсивною, якщо вона викликає іншу функцію, наприклад fun_new, а fun_new викликає fun прямо чи опосередковано. Різниця між прямою та непрямою рекурсією проілюстрована в таблиці 1.

 // An example of direct recursion void directRecFun() { // Some code.... directRecFun(); // Some code... } // An example of indirect recursion void indirectRecFun1() { // Some code... indirectRecFun2(); // Some code... } void indirectRecFun2() { // Some code... indirectRecFun1(); // Some code... }>

Яка різниця між хвостовою та нехвостою рекурсією?
Рекурсивна функція є хвостовою рекурсивною, якщо рекурсивний виклик є останнім, що виконується функцією. Будь ласка, зверніться стаття хвостової рекурсії для деталей.

Як пам'ять розподіляється для викликів різних функцій у рекурсії?
Коли будь-яка функція викликається з main(), їй виділяється пам'ять у стеку. Рекурсивна функція викликає сама себе, пам’ять для викликаної функції виділяється поверх пам’яті, виділеної для функції, що викликає, і для кожного виклику функції створюється інша копія локальних змінних. Коли базовий варіант досягнуто, функція повертає своє значення функції, якою вона була викликана, пам’ять звільняється, і процес продовжується.
Розглянемо приклад роботи рекурсії, взявши просту функцію.

CPP




// A C++ program to demonstrate working of> // recursion> #include> using> namespace> std;> > void> printFun(>int> test)> {> >if> (test <1)> >return>;> >else> {> >cout << test <<>' '>;> >printFun(test - 1);>// statement 2> >cout << test <<>' '>;> >return>;> >}> }> > // Driver Code> int> main()> {> >int> test = 3;> >printFun(test);> }>

>

>

Java




підключення java
// A Java program to demonstrate working of> // recursion> class> GFG {> >static> void> printFun(>int> test)> >{> >if> (test <>1>)> >return>;> >else> {> >System.out.printf(>'%d '>, test);> >printFun(test ->1>);>// statement 2> >System.out.printf(>'%d '>, test);> >return>;> >}> >}> > >// Driver Code> >public> static> void> main(String[] args)> >{> >int> test =>3>;> >printFun(test);> >}> }> > // This code is contributed by> // Smitha Dinesh Semwal>

>

>

Python3




# A Python 3 program to> # demonstrate working of> # recursion> > > def> printFun(test):> > >if> (test <>1>):> >return> >else>:> > >print>(test, end>=>' '>)> >printFun(test>->1>)># statement 2> >print>(test, end>=>' '>)> >return> > # Driver Code> test>=> 3> printFun(test)> > # This code is contributed by> # Smitha Dinesh Semwal>

>

>

C#




// A C# program to demonstrate> // working of recursion> using> System;> > class> GFG {> > >// function to demonstrate> >// working of recursion> >static> void> printFun(>int> test)> >{> >if> (test <1)> >return>;> >else> {> >Console.Write(test +>' '>);> > >// statement 2> >printFun(test - 1);> > >Console.Write(test +>' '>);> >return>;> >}> >}> > >// Driver Code> >public> static> void> Main(String[] args)> >{> >int> test = 3;> >printFun(test);> >}> }> > // This code is contributed by Anshul Aggarwal.>

>

>

PHP




// PHP program to demonstrate // working of recursion // function to demonstrate // working of recursion function printFun($test) { if ($test <1) return; else { echo('$test '); // statement 2 printFun($test-1); echo('$test '); return; } } // Driver Code $test = 3; printFun($test); // This code is contributed by // Smitha Dinesh Semwal. ?>>

>

>

Javascript




> > // JavaScript program to demonstrate working of> // recursion> > function> printFun(test)> >{> >if> (test <1)> >return>;> >else> {> >document.write(test +>' '>);> >printFun(test - 1);>// statement 2> >document.write(test +>' '>);> >return>;> >}> >}> > // Driver code> >let test = 3;> >printFun(test);> > >

>

>

Вихід

3 2 1 1 2 3>

Часова складність: О(1)
Допоміжний простір: О(1)

git pull origin master

Коли printFun(3) викликається з main(), для якого виділяється пам'ять printFun(3) а тест локальної змінної ініціалізується значенням 3, а оператори з 1 по 4 надсилаються в стек, як показано на схемі нижче. Спочатку друкується «3». У заяві 2 printFun(2) викликається і виділяється пам'ять printFun(2) а тест локальної змінної ініціалізується значенням 2, а оператори з 1 по 4 надсилаються в стек. Так само printFun(2) дзвінки printFun(1) і printFun(1) дзвінки printFun(0) . printFun(0) переходить до оператора if і повертається до printFun(1) . Решта заяв в printFun(1) виконується, і він повертається до printFun(2) і так далі. У вихідних даних друкуються значення від 3 до 1, а потім друкуються значення від 1 до 3. Стек пам'яті показано на схемі нижче.

рекурсія

Рекурсія VS Ітерація

СР № Рекурсія Ітерація
1) Завершується, коли базовий випадок стає істинним. Припиняється, коли умова стає помилковою.
2) Використовується з функціями. Використовується з петлями.
3) Кожен рекурсивний виклик потребує додаткового місця в пам'яті стека. Кожна ітерація не потребує додаткового місця.
4) Менший розмір коду. Більший розмір коду.

Тепер давайте обговоримо кілька практичних проблем, які можна вирішити за допомогою рекурсії, і зрозуміємо її основні принципи роботи. Для базового розуміння прочитайте наступні статті.
Базове розуміння рекурсії.
Проблема 1: Напишіть програму та рекурентне співвідношення для знаходження ряду Фібоначчі від n, де n>2.
Математичне рівняння:

n if n == 0, n == 1; fib(n) = fib(n-1) + fib(n-2) otherwise;>

Відношення повторення:

T(n) = T(n-1) + T(n-2) + O(1)>

Рекурсивна програма:

 Input: n = 5 Output: Fibonacci series of 5 numbers is : 0 1 1 2 3>

Реалізація:

C++




// C++ code to implement Fibonacci series> #include> using> namespace> std;> > // Function for fibonacci> > int> fib(>int> n)> > > // Driver Code> int> main()> {> >// Initialize variable n.> >int> n = 5;> >cout<<>'Fibonacci series of 5 numbers is: '>;> > >// for loop to print the fibonacci series.> >for> (>int> i = 0; i { cout<' '; } return 0; }>

>

>

C




// C code to implement Fibonacci series> #include> > // Function for fibonacci> int> fib(>int> n)> > >// Stop condition> >if> (n == 0)> >return> 0;> > >// Stop condition> >if> (n == 1> > // Driver Code> int> main()> {> >// Initialize variable n.> >int> n = 5;> >printf>(>'Fibonacci series '> >'of %d numbers is: '>,> >n);> > >// for loop to print the fibonacci series.> >for> (>int> i = 0; i printf('%d ', fib(i)); } return 0; }>

>

>

Java




// Java code to implement Fibonacci series> import> java.util.*;> > class> GFG> {> > // Function for fibonacci> static> int> fib(>int> n)> > > // Driver Code> public> static> void> main(String []args)> {> > >// Initialize variable n.> >int> n =>5>;> >System.out.print(>'Fibonacci series of 5 numbers is: '>);> > >// for loop to print the fibonacci series.> >for> (>int> i =>0>; i { System.out.print(fib(i)+' '); } } } // This code is contributed by rutvik_56.>

>

>

Python3




# Python code to implement Fibonacci series> > # Function for fibonacci> def> fib(n):> > ># Stop condition> >if> (n>=>=> 0>):> >return> 0> > ># Stop condition> >if> (n>=>=> 1> or> n>=>=> 2>):> >return> 1> > ># Recursion function> >else>:> >return> (fib(n>-> 1>)>+> fib(n>-> 2>))> > > # Driver Code> > # Initialize variable n.> n>=> 5>;> print>(>'Fibonacci series of 5 numbers is :'>,end>=>' '>)> > # for loop to print the fibonacci series.> for> i>in> range>(>0>,n):> >print>(fib(i),end>=>' '>)>

>

>

C#




using> System;> > public> class> GFG> {> > >// Function for fibonacci> >static> int> fib(>int> n)> > n == 2)> >return> 1;> > >// Recursion function> >else> >return> (fib(n - 1) + fib(n - 2));> >> > >// Driver Code> >static> public> void> Main ()> >{> > >// Initialize variable n.> >int> n = 5;> >Console.Write(>'Fibonacci series of 5 numbers is: '>);> > >// for loop to print the fibonacci series.> >for> (>int> i = 0; i { Console.Write(fib(i) + ' '); } } } // This code is contributed by avanitrachhadiya2155>

>

>

Javascript




> // JavaScript code to implement Fibonacci series> > // Function for fibonacci> function> fib(n)> n == 2)> >return> 1;> >// Recursion function> >else> >return> fib(n-1) + fib(n-2);> > > // Initialize variable n.> let n = 5;> > document.write(>'Fibonacci series of 5 numbers is: '>);> > // for loop to print the fibonacci series.> for>(let i = 0; i { document.write(fib(i) + ' '); }>

>

>

Вихід

Fibonacci series of 5 numbers is: 0 1 1 2 3>

Часова складність: O(2п)
Допоміжний простір: O(n)

Ось рекурсивне дерево для входу 5, яке показує чітку картину того, як велику проблему можна розв’язати на менші.
fib(n) є функцією Фібоначчі. Часова складність заданої програми може залежати від виклику функції.

fib(n) -> рівень CBT (UB) -> 2^n-1 вузлів -> виклик функції 2^n -> 2^n*O(1) -> T(n) = O(2^n)

Для кращого випадку.

T(n) = ?(2^n2)>

Працює:

Проблема 2: Напишіть програму та рекурентне співвідношення, щоб знайти факторіал n, де n>2.
Математичне рівняння:

1 if n == 0 or n == 1; f(n) = n*f(n-1) if n>1;>

Відношення повторення:

T(n) = 1 for n = 0 T(n) = 1 + T(n-1) for n>0>

Рекурсивна програма:
введення: n = 5
Вихід:
факторіал 5 дорівнює: 120
Реалізація:

C++




// C++ code to implement factorial> #include> using> namespace> std;> > // Factorial function> int> f(>int> n)> n == 1)> >return> 1;> > >// Recursive condition> >else> >return> n * f(n - 1);> > > // Driver code> int> main()> {> >int> n = 5;> >cout<<>'factorial of '><' is: '< return 0; }>

>

>

C




// C code to implement factorial> #include> > // Factorial function> int> f(>int> n)> > >// Stop condition> >if> (n == 0> > // Driver code> int> main()> {> >int> n = 5;> >printf>(>'factorial of %d is: %d'>, n, f(n));> >return> 0;> }>

>

>

Java




// Java code to implement factorial> public> class> GFG> {> > >// Factorial function> >static> int> f(>int> n)> >> > >// Driver code> >public> static> void> main(String[] args)> >{> >int> n =>5>;> >System.out.println(>'factorial of '> + n +>' is: '> + f(n));> >}> }> > // This code is contributed by divyesh072019.>

>

>

Python3




# Python3 code to implement factorial> > # Factorial function> def> f(n):> > ># Stop condition> >if> (n>=>=> 0> or> n>=>=> 1>):> >return> 1>;> > ># Recursive condition> >else>:> >return> n>*> f(n>-> 1>);> > > # Driver code> if> __name__>=>=>'__main__'>:> > >n>=> 5>;> >print>(>'factorial of'>,n,>'is:'>,f(n))> > ># This code is contributed by pratham76.>

>

>

C#




// C# code to implement factorial> using> System;> class> GFG {> > >// Factorial function> >static> int> f(>int> n)> > n == 1)> >return> 1;> > >// Recursive condition> >else> >return> n * f(n - 1);> >> > >// Driver code> >static> void> Main()> >{> >int> n = 5;> >Console.WriteLine(>'factorial of '> + n +>' is: '> + f(n));> >}> }> > // This code is contributed by divyeshrabadiya07.>

>

>

Javascript




1 з 1000

> // JavaScript code to implement factorial> > // Factorial function> function> f(n)> n == 1)> >return> 1;> > >// Recursive condition> >else> >return> n*f(n-1);> > > // Initialize variable n.> let n = 5;> document.write(>'factorial of '>+ n +>' is: '> + f(n));> > // This code is contributed by probinsah.> >

>

>

Вихід

factorial of 5 is: 120>

Часова складність: O(n)
Допоміжний простір: O(n)

Працює:

Діаграма функції факториальної рекурсії для введення користувача 5.

Приклад: реальне застосування рекурсії в реальних задачах

Рекурсія — потужна техніка, яка має багато застосувань у інформатиці та програмуванні. Ось деякі з поширених застосувань рекурсії:

    Обхід дерева та графа: рекурсія часто використовується для обходу та пошуку структур даних, таких як дерева та графіки. Рекурсивні алгоритми можна використовувати для систематичного дослідження всіх вузлів або вершин дерева чи графа. Алгоритми сортування: рекурсивні алгоритми також використовуються в таких алгоритмах сортування, як швидке сортування та сортування злиттям. Ці алгоритми використовують рекурсію, щоб розділити дані на менші підмасиви або підсписки, відсортувати їх, а потім знову об’єднати. Алгоритми розділяй і володарюй: багато алгоритмів, які використовують підхід розділяй і володарюй, наприклад алгоритм бінарного пошуку, використовують рекурсію, щоб розбити проблему на менші підпроблеми. Фрактальна генерація: Фрактальні форми та шаблони можна генерувати за допомогою рекурсивних алгоритмів. Наприклад, множина Мандельброта генерується повторним застосуванням рекурсивної формули до комплексних чисел. Алгоритми зворотного відстеження: Алгоритми зворотного відстеження використовуються для вирішення проблем, які включають прийняття послідовності рішень, де кожне рішення залежить від попередніх. Ці алгоритми можна реалізувати за допомогою рекурсії для дослідження всіх можливих шляхів і повернення назад, якщо рішення не знайдено. Запам'ятовування: Запам'ятовування - це техніка, яка передбачає збереження результатів дорогих викликів функцій і повернення кешованого результату, коли ті самі введення повторюються знову. Запам'ятовування може бути реалізовано за допомогою рекурсивних функцій для обчислення та кешування результатів підпроблем.

Це лише кілька прикладів із багатьох застосувань рекурсії в інформатиці та програмуванні. Рекурсія — це універсальний і потужний інструмент, який можна використовувати для вирішення багатьох різних типів задач.

Пояснення: один реальний приклад рекурсії:

Рекурсія — це техніка програмування, яка передбачає виклик самої функції. Це може бути потужним інструментом для вирішення складних проблем, але він також вимагає ретельної реалізації, щоб уникнути нескінченних циклів і переповнення стека.

Ось приклад реалізації рекурсії в Python:

C++




розмір мого монітора
#include> using> namespace> std;> int> factorial(>int> n)> {> > >// Base case: if n is 0 or 1, return 1> >if> (n == 0 || n == 1) {> >return> 1;> >}> > >// Recursive case: if n is greater than 1,> >// call the function with n-1 and multiply by n> >else> {> >return> n * factorial(n - 1);> >}> }> > int> main()> {> > >// Call the factorial function and print the result> >int> result = factorial(5);> >cout << result

>

>

Java




import> java.util.*;> > class> Main {> >public> static> int> factorial(>int> n)> >{> >// Base case: if n is 0 or 1, return 1> >if> (n ==>0> || n ==>1>) {> >return> 1>;> >}> > >// Recursive case: if n is greater than 1,> >// call the function with n-1 and multiply by n> >else> {> >return> n * factorial(n ->1>);> >}> >}> > >public> static> void> main(String[] args)> >{> >// Call the factorial function and print the result> >int> result = factorial(>5>);> >System.out.println(result);>// Output: 120> >}> }>

>

>

Python3




def> factorial(n):> ># Base case: if n is 0 or 1, return 1> >if> n>=>=> 0> or> n>=>=> 1>:> >return> 1> > ># Recursive case: if n is greater than 1, call the function with n-1 and multiply by n> >else>:> >return> n>*> factorial(n>->1>)> > # Call the factorial function and print the result> result>=> factorial(>5>)> print>(result)># Output: 120>

>

>

C#




using> System;> > class> MainClass {> >public> static> int> factorial(>int> n)> >{> >// Base case: if n is 0 or 1, return 1> >if> (n == 0 || n == 1) {> >return> 1;> >}> > >// Recursive case: if n is greater than 1,> >// call the function with n-1 and multiply by n> >else> {> >return> n * factorial(n - 1);> >}> >}> > >public> static> void> Main (>string>[] args) {> >// Call the factorial function and print the result> >int> result = factorial(5);> >Console.WriteLine(result);>// Output: 120> >}> }>

>

>

Javascript




function> factorial(n) {> >// Base case: if n is 0 or 1, return 1> >if> (n === 0 || n === 1) {> >return> 1;> >}> > >// Recursive case: if n is greater than 1, call the function with n-1 and multiply by n> >else> {> >return> n * factorial(n - 1);> >}> }> > // Call the factorial function and print the result> const result = factorial(5);> console.log(result);>// Output: 120>

>

>

Вихід

120>

У цьому прикладі ми визначаємо функцію факторіал, яка приймає ціле число n як вхідні дані. Функція використовує рекурсію для обчислення факториалу n (тобто добутку всіх додатних чисел до n).

Функція факторіалу спочатку перевіряє, чи n дорівнює 0 чи 1, які є базовими випадками. Якщо n дорівнює 0 або 1, функція повертає 1, оскільки 0! і 1! обидва 1.

Якщо n більше 1, функція переходить у рекурсивний регістр. Він викликає себе з n-1 як аргументом і множить результат на n. Це обчислює n! шляхом рекурсивного обчислення (n-1)!.

Важливо зауважити, що рекурсія може бути неефективною та призвести до переповнення стека, якщо не використовувати її обережно. Кожен виклик функції додає новий кадр до стеку викликів, що може призвести до того, що стек стане занадто великим, якщо рекурсія занадто глибока. Крім того, рекурсія може зробити код більш складним для розуміння та налагодження, оскільки вона вимагає думати про кілька рівнів викликів функцій.

Однак рекурсія також може бути потужним інструментом для вирішення складних проблем, особливо тих, які включають розбиття проблеми на менші підпроблеми. При правильному використанні рекурсія може зробити код більш елегантним і легшим для читання.

Які недоліки рекурсивного програмування перед ітеративним?
Зауважте, що як рекурсивні, так і ітераційні програми мають однакові можливості для вирішення проблем, тобто кожна рекурсивна програма може бути написана ітераційно, і навпаки. Рекурсивна програма має більші вимоги до простору, ніж ітеративна програма, оскільки всі функції залишатимуться в стеку, доки не буде досягнуто базовий варіант. Він також потребує більше часу через виклики функцій і накладні витрати.

Крім того, через меншу довжину коду, коди важко зрозуміти, і, отже, потрібно бути особливо уважним під час написання коду. Комп’ютеру може бракувати пам’яті, якщо рекурсивні виклики не перевірено належним чином.

Які переваги рекурсивного програмування перед ітеративним програмуванням?
Рекурсія забезпечує чистий і простий спосіб написання коду. Деякі проблеми за своєю суттю рекурсивні, як обхід дерева, Ханойська вежа , тощо. Для таких проблем краще писати рекурсивний код. Ми можемо писати такі коди також ітераційно за допомогою стекової структури даних. Наприклад, зверніться до Inorder Tree Traversal without Recursion, Iterative Tower of Hanoi.

Резюме рекурсії:

  • У рекурсії є два типи випадків, тобто рекурсивний випадок і базовий випадок.
  • Базовий випадок використовується для завершення рекурсивної функції, коли виявляється, що випадок є істинним.
  • Кожен рекурсивний виклик створює нову копію цього методу в пам'яті стека.
  • Нескінченна рекурсія може призвести до вичерпання пам'яті стека.
  • Приклади рекурсивних алгоритмів: сортування злиттям, швидке сортування, Ханойська вежа, ряд Фібоначчі, факторна задача тощо.

Практичні задачі на основі результатів для початківців:
Практичні запитання для рекурсії | Набір 1
Практичні запитання для рекурсії | Набір 2
Практичні запитання для рекурсії | Набір 3
Практичні запитання для рекурсії | Набір 4
Практичні запитання для рекурсії | Набір 5
Практичні запитання для рекурсії | Набір 6
Практичні запитання для рекурсії | Набір 7
Тест з рекурсії
Практика кодування на рекурсії:
Усі статті про рекурсію
Рекурсивні практичні задачі з рішеннями