├── README.md ├── section-01-essential-python-concepts ├── 01-basic-data-types-in-python.py ├── 02-basic-builtin-functions-in-python.py └── README.md ├── section-02-basic-prerequisites ├── 01-memory-management-in-python.py ├── 02-abstract-data-types.py ├── 03-time-and-space-complexity.py └── README.md └── section-03-recursion ├── 01-recursion-introduction.py └── 02-tail-recursion-and-head-recursion.py /README.md: -------------------------------------------------------------------------------- 1 |

Mastering Data Structure and Algorithms Using Python

2 | 3 | **In this repo I will try to cover Abdul Bari Sir's [Mastering Data Structures & Algorithms using C and C++](https://www.udemy.com/course/datastructurescncpp/) course codes in a _Pythonic_ way.** 4 | 5 | **Repository Notes** 6 | 7 | * You must have basic level of python coding knowledge. 8 | * In this repository I only cover coding parts with minimal explanations. 9 | * Detailed explanations I will added in my [LinkedIn](https://www.linkedin.com/in/tssovi/) and [Medium](https://medium.com/@tssovi) as post. 10 | 11 | **Find Further Details In LinkedIn:** 12 | [Mastering DS & Algo Using Python - LinkedIn](http://bit.ly/mastering-ds-algo-using-python-linkedin) 13 | 14 | **Find Further Details In Medium:** 15 | [Mastering DS & Algo Using Python - Medium](http://bit.ly/mastering-ds-algo-using-python-medium) 16 | 17 | ### Repository Content 18 | 19 | **Section 01: Essential Python Concepts** 20 | 21 | > [01 - Basic Data Types In Python](http://bit.ly/2TQQKl3)\ 22 | > [02 - Basic Builtin Functions In Python](http://bit.ly/2TRU3s6) 23 | 24 | **Section 02: Basic Prerequisites** 25 | 26 | > [01 - Memory Management In Python](http://bit.ly/3cXj4tn)\ 27 | > [02 - Abstract Data Type (ADT)](http://bit.ly/2vnCjLT)\ 28 | > [03 - Time and Space Complexity](http://bit.ly/2IQyUs5) 29 | 30 | **Section 03: Recursion** 31 | 32 | > [01 - Recursion Introduction](http://bit.ly/2wZlQ0V)\ 33 | > [02 - Tail Recursion and Head Recursion](https://bit.ly/2UA3prA)\ 34 | > 03 - Tree Recursion\ 35 | > 04 - Indirect Recursion\ 36 | > 05 - Nested Recursion\ 37 | > 06 - Sum of Natural Number Using Recursion\ 38 | > 07 - Factorial Using Recursion\ 39 | > 08 - Power Using Recursion\ 40 | > 09 - Taylor Series Using Recursion\ 41 | > 10 - Taylor Series Using Horner's Rule Recursion\ 42 | > 11 - Fibonacci Series Using Recursion - Memorization\ 43 | > 12 - nCr Using Recursion\ 44 | > 13 - Tower of Hanoi Problem Using Recursion 45 | 46 | **Section 04: Arrays Representations** 47 | 48 | > 01 - Introduction to Array\ 49 | > 02 - Declarations of Array\ 50 | > 03 - Static vs Dynamic Arrays\ 51 | > 04 - How to Increase Array Size\ 52 | > 05 - 2D Arrays\ 53 | > 06 - Array Representation by Compiler\ 54 | > 07 - Row Major Formula for 2D Arrays\ 55 | > 08 - Column Major Formula for 2D Arrays\ 56 | > 09 - Formulas for nD Arrays\ 57 | > 10 - Formulas for 3D Arrays 58 | 59 | **Section 05: Array ADT** 60 | 61 | > 01 - Array ADT\ 62 | > 02 - Inserting in an Array\ 63 | > 03 - Deleting from Array\ 64 | > 04 - Linear Search\ 65 | > 05 - Binary Search\ 66 | > 06 - Get( ) Set( ) Avg( ) Max( ) functions on Array\ 67 | > 07 - Reverse and Shift an Array\ 68 | > 08 - Check if Array is Sorted\ 69 | > 09 - Merging Arrays\ 70 | > 10 - Set operations on Array - Union, Intersection and Difference\ 71 | > 11 - Finding Missing Element(s) in an Array\ 72 | > 12 - Finding Duplicates in a Sorted Array\ 73 | > 13 - Finding Duplicates in Sorted Array Using Hashing\ 74 | > 14 - Finding Duplicates in a Unsorted Array\ 75 | > 15 - Finding a Pair of Elements with sum K\ 76 | > 16 - Finding a Pair of Elements with sum K in Sorted Array\ 77 | > 17 - Finding Max and Min in a Single Scan 78 | 79 | **Section 06: Strings** 80 | 81 | > 01 - Introduction to Strings\ 82 | > 02 - Finding Length of a String\ 83 | > 03 - Changing Case of a String\ 84 | > 04 - Counting Words and Vowels in a String\ 85 | > 05 - Validating a String\ 86 | > 06 - Reversing a String\ 87 | > 07 - Comparing Strings and Checking Palindrome\ 88 | > 08 - Finding Duplicates in a String\ 89 | > 09 - Finding Duplicates in a String Using Bitwise Operations\ 90 | > 10 - Checking if 2 Strings are Anagram\ 91 | > 11 - Permutation of String 92 | 93 | **Section 07: Matrices** 94 | 95 | > 01 - Diagonal Matrix\ 96 | > 02 - Lower Triangular Matrix Row-Major Mapping\ 97 | > 03 - Lower Triangular Matrix Column-Major Mapping\ 98 | > 04 - Upper Triangular Matrix Row-Major Mapping\ 99 | > 05 - Upper Triangular Matrix Column-Major Mapping\ 100 | > 06 - Symmetric Matrix\ 101 | > 07 - Tri-Diagonal and Tri-Band Matrix\ 102 | > 08 - Toeplitz Matrix\ 103 | > 09 - Menu Driven Program for Matrices\ 104 | > 10 - Menu Driven Program for Matrices Using Functions 105 | 106 | **Section 08: Sparse Matrix and Polynomial Representation** 107 | 108 | > 01 - Sparse Matrix Representation\ 109 | > 02 - Array Representation of Sparse Matrix\ 110 | > 03 - Addition of Sparse Matrices\ 111 | > 04 - Polynomial 112 | 113 | **Section 09: Linked List** 114 | 115 | > 01 - Display Linked List\ 116 | > 02 - Recursive Display of Linked List\ 117 | > 03 - Counting Nodes in a Linked List\ 118 | > 04 - Sum of All Elements in a Linked List\ 119 | > 05 - Maximum Element in a Linked List\ 120 | > 06 - Searching in a Linked List\ 121 | > 07 - Inserting in a Linked List\ 122 | > 08 - Creating a Linked List by Inserting at Last\ 123 | > 09 - Inserting in a Sorted Linked List\ 124 | > 10 - Deleting from Linked List\ 125 | > 11 - Check if a Linked List is Sorted\ 126 | > 12 - Remove Duplicates from Linked List\ 127 | > 13 - Reversing a Linked List\ 128 | > 14 - Recursive Reverse for Linked List\ 129 | > 15 - Concatenating 2 Linked Lists\ 130 | > 16 - Merging 2 Linked Lists\ 131 | > 17 - Check for LOOP in Linked List\ 132 | > 18 - Circular Linked List\ 133 | > 19 - Inserting in a Circular Linked List\ 134 | > 20 - Deleting From Circular Linked List\ 135 | > 21 - Doubly Linked List\ 136 | > 22 - Insert in a Doubly Linked List\ 137 | > 23 - Deleting from Doubly Linked List\ 138 | > 24 - Reverse a Doubly Linked List\ 139 | > 25 - Circular Doubly Linked List\ 140 | > 26 - Finding Middle Element of a Linked List\ 141 | > 27 - Finding Intersecting point of Two Linked List 142 | 143 | **Section 10: Sparse Matrix and Polynomial Using Linked List** 144 | 145 | > 01 - Sparse Matrix Using Linked List\ 146 | > 02 - Polynomial Representation Using Linked List\ 147 | 148 | **Section 11: Stack** 149 | 150 | > 01 - Stack Using Array\ 151 | > 02 - Stack Using Linked List\ 152 | > 03 - Parenthesis Matching\ 153 | > 04 - Infix to Postfix Conversion\ 154 | > 05 - Associativity and Unary Operators\ 155 | > 06 - Infix to Postfix Using Stack Method\ 156 | > 07 -Infix to Postfix with Associativity and Parenthesis\ 157 | > 08 - Evaluation of Postfix 158 | 159 | **Section 12: Queues** 160 | 161 | > 01 - Implementing Queue Using Array\ 162 | > 02 - Circular Queue\ 163 | > 03 - Queue Using Linked List\ 164 | > 04 - Double Ended Queue Dequeue\ 165 | > 05 - Priority Queues\ 166 | > 06 - Queue Using 2 Stacks 167 | 168 | **Section 13: Trees** 169 | 170 | > 01 - Binary Tree\ 171 | > 02 - n-ary Trees\ 172 | > 03 - Linked Representation of Binary Tree\ 173 | > 04 - Binary Tree Traversals\ 174 | > 05 - Binary Tree Traversal Easy Method\ 175 | > 06 - Creating Binary Tree\ 176 | > 07 - Preorder Tree Traversal\ 177 | > 08 - Inorder Tree Traversals Functions\ 178 | > 09 - Iterative Preorder\ 179 | > 10 - Iterative Inorder\ 180 | > 11 - Level Order Traversal\ 181 | > 12 - Generating Tree from Traversals\ 182 | > 13 - Height and Count of Binary Tree\ 183 | > 14 - Count Leaf Nodes of a Binary Tree 184 | 185 | **Section 14: Binary Search Trees** 186 | 187 | > 01 - Binary Search Trees intro\ 188 | > 02 - Searching in a Binary Search Tree\ 189 | > 03 - Inserting in a Binary Search Tree\ 190 | > 04 - Recursive Insert in Binary Search Tree\ 191 | > 05 - Creating a Binary Search Tree\ 192 | > 06 - Deleting from Binary Search Tree\ 193 | > 07 - Generating Binary Search Trees from Preorder 194 | 195 | **Section 15: AVL Trees** 196 | 197 | > 01 - Introduction to AVL Trees\ 198 | > 02 - Inserting in AVL with Rotations\ 199 | > 03 - General form of AVL Rotations\ 200 | > 04 - Generating AVL Tree\ 201 | > 05 - Deletion from AVL Tree with Rotations\ 202 | > 06 - Height Analysis of AVL Trees 203 | 204 | **Section 16: Search Trees** 205 | 206 | > 01 - 2-3 Trees\ 207 | > 02 - 2-3-4 Trees\ 208 | > 03 - Re-Black Trees Introduction\ 209 | > 04 - Red-Black Tree creation\ 210 | > 05 - Creating Red-Black Tree similar to Creating 2-3-4 Tree\ 211 | > 06 - Red-Black Tree Deletion Cases 212 | 213 | **Section 17: Heap** 214 | 215 | > 01 - Introduction to Heap\ 216 | > 02 - Inserting in a Heap\ 217 | > 03 - Creating a Heap\ 218 | > 04 - Deleting from Heap and Heap Sort\ 219 | > 05 - Heapify - Faster Method for Creating Heap\ 220 | > 06 - Heap as Priority Queue 221 | 222 | **Section 18: Sorting Techniques** 223 | 224 | > 01 - Bubble Sort\ 225 | > 02 - Insertion Sort\ 226 | > 03 - Selection Sort\ 227 | > 04 - Quick Sort\ 228 | > 05 - Iterative Merge Sort\ 229 | > 06 - Recursive Merge Sort\ 230 | > 07 - Count Sort\ 231 | > 08 - Bin / Bucket Sort\ 232 | > 09 - Radix Sort\ 233 | > 10 - Shell Sort 234 | 235 | **Section 19: Hashing Technique** 236 | 237 | > 01 - Introduction to Hashing\ 238 | > 02 - Chaining\ 239 | > 03 - Linear Probing\ 240 | > 04 - Quadratic Probing\ 241 | > 05 - Double Hashing\ 242 | > 06 - Hash Function Ideas 243 | 244 | **Section 20: Graphs** 245 | 246 | > 01 - Introduction to Graphs\ 247 | > 02 - Representation of Undirected Graph\ 248 | > 03 - Representation of Directed Graphs\ 249 | > 04 - Breadth First Search\ 250 | > 05 - Depth First Search\ 251 | > 06 - Spanning Trees\ 252 | > 07 - Prim's Minimum Cost Spanning Tree\ 253 | > 08 - Kruskal's Minimum Cost Spanning Tree\ 254 | > 09 - Disjoint Subsets\ 255 | > 10 - Kruskal's Program 256 | -------------------------------------------------------------------------------- /section-01-essential-python-concepts/01-basic-data-types-in-python.py: -------------------------------------------------------------------------------- 1 | # Here a is int 2 | a = 5 3 | print(a, "is of type", type(a)) 4 | 5 | # Here a is float 6 | a = 2.0 7 | print(a, "is of type", type(a)) 8 | 9 | # Here a is complex 10 | a = 1+2j 11 | print(a, "is of type", type(a)) 12 | 13 | # Here a is list 14 | a = [1, 2.2, 'python'] 15 | print(a, "is of type", type(a)) 16 | 17 | # List is mutable 18 | a = [1, 2.2, 'python'] 19 | a[2] = 'list is mutable' 20 | print(a) 21 | 22 | # Here a is tuple 23 | a = (1, 2.2, 'python') 24 | print(a, "is of type", type(a)) 25 | 26 | # Tuple is immutable 27 | a = (1, 2.2, 'python') 28 | try: 29 | a[2] = 'tuple is immutable' 30 | except: 31 | print('Tuple is immutable') 32 | print(a) 33 | 34 | # Here a is single string 35 | a = "This is a string" 36 | print(a, "is of type", type(a)) 37 | 38 | # Here a is multiline string 39 | a = '''This is a multiline string 40 | Line 1 41 | Line 2''' 42 | print(a, "is of type", type(a)) 43 | 44 | # Here a is set 45 | a = {1,2,2,3,3,3} 46 | print(a, "is of type", type(a)) 47 | 48 | # Here a is dict 49 | a = {'key1':'value1','key2':'value2'} 50 | print(a, "is of type", type(a)) 51 | 52 | person = {"name": "John", "age": 23, "sex": "male"} 53 | 54 | # Here a is frozenset of person dict 55 | a = frozenset(person) 56 | print(a, "is of type", type(a)) 57 | 58 | # Here a is boolean 59 | a = True 60 | print(a, "is of type", type(a)) 61 | 62 | -------------------------------------------------------------------------------- /section-01-essential-python-concepts/02-basic-builtin-functions-in-python.py: -------------------------------------------------------------------------------- 1 | # Math related common functions 2 | 3 | # Random integer number 4 | integer = -10 5 | print('Absolute value of -10 is:', abs(integer)) 6 | 7 | # Random floating number 8 | floating = -10.33 9 | print('Absolute value of -10.33 is:', abs(floating)) 10 | 11 | # Random complex number 12 | complex = (5 - 2j) 13 | print('Magnitude of 5 - 2j is:', abs(complex)) 14 | 15 | # divmod() with intiger numbers 16 | print('Divmod of 7 and 2 is:', divmod(7, 2)) 17 | 18 | # divmod() with Floats 19 | print('Divmod of 7.5 and 2.5 is:', divmod(7.5, 2.5)) 20 | 21 | # Enumerate example 22 | grocery = ['bread', 'milk', 'butter'] 23 | 24 | for count, item in enumerate(grocery): 25 | print(count, item) 26 | 27 | # changing default start value 28 | for count, item in enumerate(grocery, 100): 29 | print(count, item) 30 | 31 | # Max value from a list 32 | numbers = [3, 2, 8, 5, 10, 6] 33 | largest_number = max(numbers) 34 | 35 | print("The largest number from numbers list is:", largest_number) 36 | 37 | # Max value from a list 38 | numbers = [3, 2, 8, 5, 10, 6] 39 | smallest_number = min(numbers) 40 | 41 | print("The smallest number from numbers list is:", smallest_number) 42 | 43 | # Power calculation 44 | x = 7 45 | y = 2 46 | z = 5 47 | 48 | print('Power of x & y is:', pow(x, y)) 49 | print('Power of x, y & z is:', pow(x, y, z)) 50 | 51 | # Round numbers 52 | x = 5.756 53 | 54 | print('Round of x without decimal points is:', round(x)) 55 | print('Round of x for 2 decimal points is:', round(x, 2)) 56 | 57 | # Sum of a list 58 | numbers = [2.5, 3, 4, -5] 59 | 60 | # start parameter is not provided 61 | numbers_sum = sum(numbers) 62 | print('Sum of all variable in numbers list is:', numbers_sum) 63 | 64 | # start = 10 65 | numbers_sum = sum(numbers, 10) 66 | print('Sum of all variable in numbers list with 10 is:', numbers_sum) 67 | 68 | # Slice to get a substring from the given string 69 | string = 'Python' 70 | 71 | # stop = 3 72 | # contains 0, 1 and 2 indices 73 | slice_object = slice(3) 74 | print('Substing of Python is:', string[slice_object]) 75 | 76 | # start = 1, stop = 6, step = 2 77 | # contains 1, 3 and 5 indices 78 | slice_object = slice(1, 6, 2) 79 | print('Substing of Python is:', string[slice_object]) -------------------------------------------------------------------------------- /section-01-essential-python-concepts/README.md: -------------------------------------------------------------------------------- 1 |

Section 01: Essential Python Concepts

2 | 3 | **Find Further Details In LinkedIn:** 4 | > [01 - Basic Data Types In Python - LinkedIn](http://bit.ly/3aWDhxQ)\ 5 | > [02 - Basic Builtin Functions In Python - LinkedIn](http://bit.ly/3aSxLMD) 6 | 7 | **Find Further Details In Medium:** 8 | > [01 - Basic Data Types In Python - Medium](http://bit.ly/33hFfGp)\ 9 | > [02 - Basic Builtin Functions In Python - Medium](http://bit.ly/3aWPgeQ) -------------------------------------------------------------------------------- /section-02-basic-prerequisites/01-memory-management-in-python.py: -------------------------------------------------------------------------------- 1 | # Instead of adding line1, line2 to text individually, use list and join 2 | # Don’t do this: 3 | 4 | text = 'line1\n' 5 | text += 'line2' 6 | print(text) 7 | 8 | # Better do this 9 | list=['line1', 'line2'] 10 | text = '\n'.join(list) 11 | print(text) 12 | 13 | # Don’t use the + operator for concatenation if you can avoid it 14 | # Don’t do this 15 | msg = '+ operator' 16 | full_msg = 'Avoid using the ' + msg + ' for strings' 17 | print(full_msg) 18 | 19 | # Better do this 20 | full_msg = 'Avoid using the %s for strings' % msg 21 | print(full_msg) 22 | 23 | # Or this 24 | full_msg = 'Avoid using the {} for strings'.format(msg) 25 | print(full_msg) 26 | 27 | # Assign a function to a local variable 28 | class MathFunctions(): 29 | def sum(a, b): 30 | return a + b 31 | 32 | sum = MathFunctions.sum 33 | a = 5 34 | b = 6 35 | 36 | res = sum(a, b) 37 | print('Summation of a and b is:', res) 38 | 39 | # Use builtin functions and libraries rather than raw codes 40 | # Don’t do this 41 | word_list = ['python', 'is', 'awesome'] 42 | new_list = [] 43 | for myword in word_list: 44 | new_list.append(myword.upper()) 45 | print(new_list) 46 | 47 | # Better do this 48 | new_list = map(str.upper, word_list) 49 | 50 | # Convert map object to tuple to print 51 | print(tuple(new_list)) 52 | -------------------------------------------------------------------------------- /section-02-basic-prerequisites/02-abstract-data-types.py: -------------------------------------------------------------------------------- 1 | # STack ADT 2 | class Stack: 3 | def __init__(self): 4 | self.items = [] 5 | 6 | def isEmpty(self): 7 | return self.items == [] 8 | 9 | def push(self, item): 10 | self.items.append(item) 11 | 12 | def pop(self): 13 | return self.items.pop() 14 | 15 | def peek(self): 16 | return self.items[len(self.items) - 1] 17 | 18 | def size(self): 19 | return len(self.items) 20 | 21 | 22 | # Queue ADT 23 | class Queue: 24 | def __init__(self): 25 | self.items = [] 26 | 27 | def isEmpty(self): 28 | return self.items == [] 29 | 30 | def enqueue(self,item): 31 | self.items.append(item) 32 | 33 | def dequeue(self): 34 | return self.items.pop(0) 35 | 36 | def front(self): 37 | return self.items[len(self.items)-1] 38 | 39 | def size(self): 40 | return len(self.items) 41 | 42 | 43 | # STack ADT operation example 44 | s=Stack() 45 | 46 | print('Stack operation examples') 47 | print(s.isEmpty()) 48 | s.push(5) 49 | s.push('python') 50 | print(s.peek()) 51 | s.push(True) 52 | print(s.size()) 53 | print(s.isEmpty()) 54 | s.push(11.5) 55 | print(s.pop()) 56 | print(s.pop()) 57 | print(s.size()) 58 | 59 | 60 | # Queue ADT operation example 61 | q=Queue() 62 | 63 | print('Queue operation examples') 64 | print(q.isEmpty()) 65 | q.enqueue(5) 66 | q.enqueue('python') 67 | print(q.front()) 68 | q.enqueue(True) 69 | print(q.size()) 70 | print(q.isEmpty()) 71 | q.enqueue(11.5) 72 | print(q.dequeue()) 73 | print(q.dequeue()) 74 | print(q.size()) -------------------------------------------------------------------------------- /section-02-basic-prerequisites/03-time-and-space-complexity.py: -------------------------------------------------------------------------------- 1 | # Constant Time - O(1) 2 | def get_first(data): 3 | return data[0] 4 | 5 | # Logarithmic Time - O(log n) 6 | def binary_search(alist, item): 7 | if len(alist) == 0: 8 | return False 9 | else: 10 | midpoint = len(alist)//2 11 | if alist[midpoint]==item: 12 | return True 13 | else: 14 | if item arr[j+1]: 61 | arr[j], arr[j+1] = arr[j+1], arr[j] 62 | return arr 63 | 64 | 65 | # Exponential Time - O(2^n) 66 | def fibonacci(n): 67 | if n <= 1: 68 | return n 69 | return fibonacci(n-1) + fibonacci(n-2) 70 | 71 | 72 | # Factorial - O(n!) 73 | def factorial(n): 74 | return 1 if (n == 1 or n == 0) else n * factorial(n - 1) 75 | 76 | 77 | res_data = [] 78 | def heap_permutation(data, n): 79 | if n == 1: 80 | res_data.append(data) 81 | return 82 | 83 | for i in range(n): 84 | heap_permutation(data, n - 1) 85 | if n % 2 == 0: 86 | data[i], data[n - 1] = data[n - 1], data[i] 87 | else: 88 | data[0], data[n - 1] = data[n - 1], data[0] 89 | return res_data 90 | 91 | 92 | num_arr = [58, 24, 84, 2, 30, 27, 35, 91, 14, 23, 53, 33, 99, 17, 86] 93 | l = len(num_arr) 94 | 95 | data = [1, 2, 3] 96 | n = len(data) 97 | 98 | sorted_arr = heap_sort(num_arr, l) 99 | 100 | val = get_first(num_arr) 101 | print("Result of get_first func is:", val) 102 | 103 | val = binary_search(sorted_arr, 17) 104 | print("Result of binary_search func is:", val) 105 | 106 | val = linear_search(num_arr, 17) 107 | print("Result of linear_search func is:", val) 108 | 109 | val = heap_sort(num_arr, l) 110 | print("Result of heap_sort func is:", val) 111 | 112 | val = bubble_sort(num_arr, l) 113 | print("Result of bubble_sort func is:", val) 114 | 115 | val = fibonacci(10) 116 | print("Result of fibonacci func is:", val) 117 | 118 | val = factorial(10) 119 | print("Result of factorial func is:", val) 120 | 121 | val = heap_permutation(data, n) 122 | print("Result of heap_permutation func is:", val) 123 | 124 | -------------------------------------------------------------------------------- /section-02-basic-prerequisites/README.md: -------------------------------------------------------------------------------- 1 |

Section 02: Basic Prerequisites

2 | 3 | **Find Further Details In LinkedIn:** 4 | > [01 - Memory Management In Python - LinkedIn](http://bit.ly/2QjcZhn)\ 5 | > [02 - Abstract Data Type (ADT) - LinkedIn](http://bit.ly/33hqweD)\ 6 | > [03 - Time and Space Complexity - LinkedIn](http://bit.ly/3aZ5KTG) 7 | 8 | **Find Further Details In Medium:** 9 | > [01 - Memory Management In Python - Medium](http://bit.ly/2IMoUjF)\ 10 | > [02 - Abstract Data Type (ADT) - Medium](http://bit.ly/39Qapao)\ 11 | > [03 - Time and Space Complexity - Medium](http://bit.ly/3cYl9VX) -------------------------------------------------------------------------------- /section-03-recursion/01-recursion-introduction.py: -------------------------------------------------------------------------------- 1 | def factorial(n): 2 | if n == 1: 3 | return 1 4 | else: 5 | return (n * factorial(n - 1)) 6 | 7 | 8 | def print_number_rev(n): 9 | if n > 0: 10 | print(n) 11 | print_number_rev(n - 1) 12 | 13 | 14 | def print_number(n): 15 | if n > 0: 16 | print_number(n - 1) 17 | print(n) 18 | 19 | 20 | num = 5 21 | 22 | print_number_rev(num) 23 | print_number(num) 24 | print("The factorial of", num, "is", factorial(num)) 25 | -------------------------------------------------------------------------------- /section-03-recursion/02-tail-recursion-and-head-recursion.py: -------------------------------------------------------------------------------- 1 | # normal recursive of factorial 2 | def factorial(n): 3 | if n == 0: 4 | return 1 5 | else: 6 | return n * factorial(n - 1) 7 | 8 | 9 | # tail recursive version of factorial 10 | def tail_factorial(n, num=1): 11 | if n == 0: 12 | return num 13 | else: 14 | return tail_factorial(n - 1, num * n) 15 | 16 | # head recursive version of factorial 17 | def head_factorial(n, num=1): 18 | if n > 0: 19 | return head_factorial(n - 1, num * n) 20 | else: 21 | return num 22 | 23 | # for loop version of factorial 24 | def loop_factorial(n): 25 | num = 1 26 | for i in range(1, n + 1): 27 | num = num * i 28 | return num 29 | 30 | 31 | 32 | print(factorial(5)) 33 | print(tail_factorial(5)) 34 | print(head_factorial(5)) 35 | print(loop_factorial(5)) --------------------------------------------------------------------------------