Recursion is a fundamental technique in data structures and algorithms where a function solves a problem by calling itself on progressively smaller sub-problems. Rather than relying on explicit loops, a recursive function delegates work to a reduced version of itself, unwinding only once a base case is reached. Understanding recursion unlocks elegant solutions to problems like searching sorted sequences, computing combinatorial values, and traversing tree-based structures.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/tutosrive/ed/llms.txt
Use this file to discover all available pages before exploring further.
What is Recursion?
Every recursive function has two essential components:Base Case
The condition that stops the recursion. Without it, the function would call itself forever and exhaust the call stack. The base case returns a concrete value immediately, without making another recursive call.
Binary Search (LIFO / Stack Recursion)
Binary search is a classic example of stack (LIFO) recursion. Given a sorted list, it repeatedly halves the search space by comparing the target value against the middle element, recursing left or right until the element is found or the search space is exhausted.binary_search.py
Compute the midpoint
medio = (left + right) // 2 finds the index of the middle element in the current search window.Check base cases
If
medio is out of bounds (medio > len(lista) - 1) or the window has collapsed (right < left), the value does not exist — return -1. If lista[medio] == value, the element is found — return its index.Narrow the search window
If the target is greater than the middle element, move
left to medio + 1 (search the right half). Otherwise, move right to medio - 1 (search the left half).The list must be sorted before calling
binary_search. In the workshop, list_integer.sort() is called on the raw input before passing it to the function. Passing an unsorted list produces undefined behaviour.Fibonacci with Memoization (Stack Recursion)
The naive recursive Fibonacci recurrence —fib(n) = fib(n-1) + fib(n-2) — recomputes the same sub-problems exponentially many times, giving O(2ⁿ) time complexity. Memoization solves this by caching results in a dictionary the moment they are computed, so any subsequent request for the same value is answered in O(1) without a new recursive call.
fibonacci_2.py
valuesis a shared dictionary pre-seeded with{0: 0, 1: 1}— the two base cases of the Fibonacci sequence.- Before recursing to compute
fib(n-1), the function checksvalues.get(n-1). If the result is already cached, it is used directly; otherwisefibonacci_2is called recursively and the result is stored invalues. - The same logic applies to
fib(n-2). - This reduces the time complexity from O(2ⁿ) to O(n) because each unique sub-problem is solved exactly once.
Always pass a fresh dictionary pre-seeded with
{0: 0, 1: 1} on each top-level call. Because Python mutable default arguments persist across calls, relying on a default dict parameter would cause the cache from a previous call to interfere with the next one.