Spaces:
Sleeping
Sleeping
| RECURSION | |
| ========= | |
| Recursion is when a function calls itself to solve a smaller version of the same problem. | |
| Every recursive function needs: | |
| 1. Base case — condition to stop recursion. | |
| 2. Recursive case — function calls itself with smaller input. | |
| --- Factorial --- | |
| n! = n * (n-1) * ... * 1 | |
| def factorial(n): | |
| if n == 0 or n == 1: # base case | |
| return 1 | |
| return n * factorial(n - 1) # recursive case | |
| print(factorial(5)) # 120 | |
| print(factorial(0)) # 1 | |
| # Iterative equivalent | |
| def factorial_iter(n): | |
| result = 1 | |
| for i in range(2, n + 1): | |
| result *= i | |
| return result | |
| --- Fibonacci --- | |
| fib(n) = fib(n-1) + fib(n-2), fib(0)=0, fib(1)=1 | |
| def fib(n): | |
| if n <= 1: | |
| return n | |
| return fib(n-1) + fib(n-2) | |
| print([fib(i) for i in range(8)]) # [0, 1, 1, 2, 3, 5, 8, 13] | |
| --- Sum of Array --- | |
| def array_sum(arr): | |
| if not arr: | |
| return 0 | |
| return arr[0] + array_sum(arr[1:]) | |
| print(array_sum([1, 2, 3, 4, 5])) # 15 | |
| --- Power Function --- | |
| def power(base, exp): | |
| if exp == 0: | |
| return 1 | |
| if exp % 2 == 0: | |
| half = power(base, exp // 2) | |
| return half * half # O(log n) — fast power | |
| return base * power(base, exp - 1) | |
| print(power(2, 10)) # 1024 | |
| print(power(3, 5)) # 243 | |
| --- Reverse a String --- | |
| def reverse_string(s): | |
| if len(s) <= 1: | |
| return s | |
| return reverse_string(s[1:]) + s[0] | |
| print(reverse_string("hello")) # "olleh" | |
| --- Check Palindrome --- | |
| def is_palindrome(s): | |
| if len(s) <= 1: | |
| return True | |
| if s[0] != s[-1]: | |
| return False | |
| return is_palindrome(s[1:-1]) | |
| print(is_palindrome("racecar")) # True | |
| print(is_palindrome("hello")) # False | |
| --- Tower of Hanoi --- | |
| Move n disks from source to destination using auxiliary peg. | |
| Minimum moves = 2^n - 1. | |
| def hanoi(n, source, destination, auxiliary): | |
| if n == 1: | |
| print(f"Move disk 1 from {source} to {destination}") | |
| return | |
| hanoi(n-1, source, auxiliary, destination) | |
| print(f"Move disk {n} from {source} to {destination}") | |
| hanoi(n-1, auxiliary, destination, source) | |
| hanoi(3, 'A', 'C', 'B') | |
| # Moves disk 1 from A to C | |
| # Moves disk 2 from A to B | |
| # Moves disk 1 from C to B | |
| # ... (7 total moves) | |
| --- Binary Search (Recursive) --- | |
| def binary_search(arr, target, low, high): | |
| if low > high: | |
| return -1 | |
| mid = (low + high) // 2 | |
| if arr[mid] == target: | |
| return mid | |
| elif arr[mid] < target: | |
| return binary_search(arr, target, mid + 1, high) | |
| else: | |
| return binary_search(arr, target, low, mid - 1) | |
| arr = [1, 3, 5, 7, 9] | |
| print(binary_search(arr, 7, 0, len(arr)-1)) # 3 | |
| --- Flatten Nested List --- | |
| def flatten(lst): | |
| result = [] | |
| for item in lst: | |
| if isinstance(item, list): | |
| result.extend(flatten(item)) | |
| else: | |
| result.append(item) | |
| return result | |
| print(flatten([1, [2, [3, 4], 5], 6])) # [1, 2, 3, 4, 5, 6] | |
| --- Generate All Subsets (Power Set) --- | |
| def subsets(nums): | |
| if not nums: | |
| return [[]] | |
| rest = subsets(nums[1:]) | |
| return rest + [[nums[0]] + s for s in rest] | |
| print(subsets([1, 2, 3])) | |
| # [[], [3], [2], [2,3], [1], [1,3], [1,2], [1,2,3]] | |
| --- Generate Permutations --- | |
| def permutations(nums): | |
| if len(nums) <= 1: | |
| return [nums] | |
| result = [] | |
| for i, num in enumerate(nums): | |
| rest = nums[:i] + nums[i+1:] | |
| for perm in permutations(rest): | |
| result.append([num] + perm) | |
| return result | |
| print(permutations([1, 2, 3])) | |
| # [[1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1]] | |
| --- Recursion vs Iteration --- | |
| Recursion: cleaner code, natural for tree/graph problems, risk of stack overflow. | |
| Iteration: better performance, no stack overflow, sometimes harder to read. | |
| Use recursion when the problem is naturally recursive (trees, divide-and-conquer). | |
| Convert to iteration for very deep recursion using an explicit stack. | |