diff --git a/Arrays/Anagram_Check_manual_Sol.py b/Arrays/AnagramCheckManualSol.py similarity index 100% rename from Arrays/Anagram_Check_manual_Sol.py rename to Arrays/AnagramCheckManualSol.py diff --git a/Arrays/Anagram_Check_Sorted_Sol.py b/Arrays/AnagramCheckSortedSol.py similarity index 100% rename from Arrays/Anagram_Check_Sorted_Sol.py rename to Arrays/AnagramCheckSortedSol.py diff --git a/Arrays/ArrayFindTheMissingElement_brute_force_sol.py b/Arrays/ArrayFindTheMissingElementBruteForceSol.py similarity index 100% rename from Arrays/ArrayFindTheMissingElement_brute_force_sol.py rename to Arrays/ArrayFindTheMissingElementBruteForceSol.py diff --git a/Arrays/ArrayFindTheMissingElement_hash_table_sol.py b/Arrays/ArrayFindTheMissingElementHashTableSol.py similarity index 100% rename from Arrays/ArrayFindTheMissingElement_hash_table_sol.py rename to Arrays/ArrayFindTheMissingElementHashTableSol.py diff --git a/Arrays/ArrayFindTheMissingElement_takingSumandSubtract_sol.py b/Arrays/ArrayFindTheMissingElementSumSol.py similarity index 100% rename from Arrays/ArrayFindTheMissingElement_takingSumandSubtract_sol.py rename to Arrays/ArrayFindTheMissingElementSumSol.py diff --git a/Arrays/ArrayFindTheMissingElement_XOR_sol.py b/Arrays/ArrayFindTheMissingElementXORSol.py similarity index 100% rename from Arrays/ArrayFindTheMissingElement_XOR_sol.py rename to Arrays/ArrayFindTheMissingElementXORSol.py diff --git a/Arrays/README.md b/Arrays/README.md index 707a82e..8f42a20 100644 --- a/Arrays/README.md +++ b/Arrays/README.md @@ -4,10 +4,10 @@ This directory contains Python implementations of common array-based algorithms ## Contents -- [Anagram Check (Sorted Solution)](Anagram_Check_Sorted_Sol.py): Checks if two strings are anagrams by comparing their sorted versions. -- [Anagram Check (Manual Solution)](Anagram_Check_manual_Sol.py): Checks if two strings are anagrams using a hash table (dictionary) to count character frequencies. -- [Array Find Missing Element (XOR Solution)](ArrayFindTheMissingElement_XOR_sol.py): Efficiently finds a missing element in a shuffled array using bitwise XOR. -- [Array Find Missing Element (Brute Force Solution)](ArrayFindTheMissingElement_brute_force_sol.py): Finds a missing element by sorting both arrays and comparing them. -- [Array Find Missing Element (Hash Table Solution)](ArrayFindTheMissingElement_hash_table_sol.py): Finds a missing element using a hash table (dictionary) to track element counts. -- [Array Find Missing Element (Sum/Subtract Solution)](ArrayFindTheMissingElement_takingSumandSubtract_sol.py): Finds a missing element by calculating the difference between the sums of the two arrays. -- [Array Pair Sum Solution](ArrayPairSumSol.py): Finds all unique pairs in an array that sum up to a specific value $k$ using a set for $O(n)$ complexity. +- [Anagram Check (Sorted Solution)](AnagramCheckSortedSol.py): Checks if two strings are anagrams by comparing their sorted versions. Time Complexity: $O(n \log n)$ +- [Anagram Check (Manual Solution)](AnagramCheckManualSol.py): Checks if two strings are anagrams using a hash table (dictionary) to count character frequencies. Time Complexity: $O(n)$ +- [Array Find Missing Element (XOR Solution)](ArrayFindTheMissingElementXORSol.py): Efficiently finds a missing element in a shuffled array using bitwise XOR. Time Complexity: $O(n)$ +- [Array Find Missing Element (Brute Force Solution)](ArrayFindTheMissingElementBruteForceSol.py): Finds a missing element by sorting both arrays and comparing them. Time Complexity: $O(n \log n)$ +- [Array Find Missing Element (Hash Table Solution)](ArrayFindTheMissingElementHashTableSol.py): Finds a missing element using a hash table (dictionary) to track element counts. Time Complexity: $O(n)$ +- [Array Find Missing Element (Sum/Subtract Solution)](ArrayFindTheMissingElementSumSol.py): Finds a missing element by calculating the difference between the sums of the two arrays. Time Complexity: $O(n)$ +- [Array Pair Sum Solution](ArrayPairSumSol.py): Finds all unique pairs in an array that sum up to a specific value $k$ using a set. Time Complexity: $O(n)$ diff --git a/deque/DequeImple.py b/Deque/DequeImple.py similarity index 100% rename from deque/DequeImple.py rename to Deque/DequeImple.py diff --git a/deque/README.md b/Deque/README.md similarity index 76% rename from deque/README.md rename to Deque/README.md index 046a17f..fc93fe9 100644 --- a/deque/README.md +++ b/Deque/README.md @@ -4,4 +4,4 @@ This directory contains Python implementations of the Deque (Double-Ended Queue) ## Contents -- [Deque Implementation](DequeImple.py): Basic implementation of a Deque using a Python list. Includes operations like `addFront`, `addRear`, `removeFront`, `removeRear`, `isEmpty`, and `size`. +- [Deque Implementation](DequeImple.py): Basic implementation of a Deque using a Python list. Includes operations like `addFront`, `addRear`, `removeFront`, `removeRear`, `isEmpty`, and `size`. Time Complexity: $O(1)$ for front operations, $O(n)$ for rear operations due to list shifting. diff --git a/Error-debug/ErrorExceptions.py b/ErrorHandling/ErrorExceptions.py similarity index 100% rename from Error-debug/ErrorExceptions.py rename to ErrorHandling/ErrorExceptions.py diff --git a/Error-debug/README.md b/ErrorHandling/README.md similarity index 73% rename from Error-debug/README.md rename to ErrorHandling/README.md index c8bc4d4..2a9cf5c 100644 --- a/Error-debug/README.md +++ b/ErrorHandling/README.md @@ -1,7 +1,7 @@ -# Error and Debugging +# Error Handling This directory contains examples of error handling and debugging techniques in Python. ## Contents -- [Error and Exceptions](ErrorExceptions.py): Demonstrates the use of `try`, `except`, `else`, and `finally` blocks for robust error handling, specifically validating integer user input. +- [Error and Exceptions](ErrorExceptions.py): Demonstrates the use of `try`, `except`, `else`, and `finally` blocks for robust error handling. diff --git a/GraphAlgorithms/README.md b/GraphAlgorithms/README.md index f0330f8..1d5f8cc 100644 --- a/GraphAlgorithms/README.md +++ b/GraphAlgorithms/README.md @@ -4,9 +4,9 @@ This directory contains Python implementations of common graph-based algorithms ## Contents -- [Adjacency List Implementation](AdjacencyListGraphImple.py): Implements the Graph Abstract Data Type (ADT) using an adjacency list (dictionaries in Python). Includes `Vertex` and `Graph` classes. -- [Breadth First Search (BFS)](BFS.py): Implements BFS to solve the Word Ladder problem, finding the shortest transformation path between words. -- [General Depth First Search (DFS)](DFSGeneral.py): Provides a general implementation of DFS, including discovery and finish times for vertices. -- [DFS - Knight's Tour Problem](DFSImpleTheKnightsTourProblem.py): Another implementation of DFS specifically tailored to the Knight's Tour puzzle. -- [The Knight's Tour Problem](TheKnightsTourProblem.py): Focuses on generating the knight's move graph and solving the tour using DFS and backtracking. -- [Word Ladder Problem](WordLadderProblem.py): Specifically focuses on building the word ladder graph where edges connect words that differ by only one letter. +- [Adjacency List Implementation](AdjacencyListGraphImple.py): Implements the Graph Abstract Data Type (ADT) using an adjacency list. Time Complexity: $O(V+E)$ +- [Breadth First Search (BFS)](BFS.py): Implements BFS to solve the Word Ladder problem. Time Complexity: $O(V+E)$ +- [General Depth First Search (DFS)](DFSGeneral.py): Provides a general implementation of DFS. Time Complexity: $O(V+E)$ +- [DFS - Knight's Tour Problem](DFSImpleTheKnightsTourProblem.py): Implementation of DFS specifically tailored to the Knight's Tour puzzle. +- [The Knight's Tour Problem](TheKnightsTourProblem.py): Focuses on generating the knight's move graph and solving the tour. Time Complexity: $O(k^N)$ +- [Word Ladder Problem](WordLadderProblem.py): Specifically focuses on building the word ladder graph. diff --git a/LinkedLists/README.md b/LinkedLists/README.md index bead21d..f8b1fcb 100644 --- a/LinkedLists/README.md +++ b/LinkedLists/README.md @@ -1,11 +1,11 @@ # Linked Lists -This directory contains Python implementations of various types of linked lists and related algorithms. +This directory contains Python implementations of linked list data structures and related problems. ## Contents -- [Singly Linked List Implementation](SingleLinkedListImple.py): Basic implementation of a singly linked list node and basic linkage. -- [Doubly Linked List Implementation](DoublyLinkedListImple.py): Basic implementation of a doubly linked list node with `prev` and `next` pointers. -- [Singly Linked List Cycle Check](SinglyLinkedListCycleCheckImple.py): Implements Floyd's Cycle-Finding Algorithm (two pointers) to detect cycles in a linked list. -- [Linked List Reversal](LinkedListReversal.py): Reverses a singly linked list in-place in $O(n)$ time. -- [Nth to Last Node](LinkedListNthToLastNode.py): Finds the $n$-th to last node in a singly linked list using two pointers. +- [Singly Linked List Implementation](SinglyLinkedListImple.py): Basic implementation of a singly linked list. Time Complexity: $O(1)$ for adding/removing at head. +- [Doubly Linked List Implementation](DoublyLinkedListImple.py): Basic implementation of a doubly linked list. Time Complexity: $O(1)$ for linkage operations. +- [Singly Linked List Cycle Check](SinglyLinkedListCycleCheckImple.py): Implementation of Floyd's cycle-finding algorithm. Time Complexity: $O(n)$ +- [Linked List Reversal](LinkedListReversal.py): In-place reversal of a linked list. Time Complexity: $O(n)$ +- [Nth to Last Node](LinkedListNthToLastNode.py): Finding the n-th to last node in a singly linked list. Time Complexity: $O(n)$ diff --git a/LinkedLists/SinglyLinkedListCycleCheckImple.py b/LinkedLists/SinglyLinkedListCycleCheckImple.py index 71a1b5c..5a302e8 100644 --- a/LinkedLists/SinglyLinkedListCycleCheckImple.py +++ b/LinkedLists/SinglyLinkedListCycleCheckImple.py @@ -19,39 +19,46 @@ def __init__(self, value): self.value = value self.nextnode = None - def cycle_check(node): - # Set two pointers initialize to passed node - pt1 = node - pt2 = node - # loop through end of the list - while pt2 != None and pt2.nextnode != None: - pt1 = pt1.nextnode - pt2 = pt2.nextnode.nextnode - # If pt2 meet pt1 then there is a cycle - if pt2 == pt1: + def cycle_check(self): + """ + Check if the linked list has a cycle using Floyd's cycle-finding algorithm. + Returns True if a cycle exists, False otherwise. + """ + # Set two pointers initialize to current node (self) + slow = self + fast = self + + # Loop through the list + while fast is not None and fast.nextnode is not None: + slow = slow.nextnode + fast = fast.nextnode.nextnode + + # If fast meets slow then there is a cycle + if fast == slow: return True + return False + # Test -# Create a Linked List -a = LinkedListNode(1) -b = LinkedListNode(2) -c = LinkedListNode(3) -# Create a cycle -a.nextnode = b -b.nextnode = c -# This is a cycle -- to test non-cycle scnerio comment this line -c.nextnode = a - -print (a.value) -print (b.value) -print (c.value) - -# Since cycle_check is a method but it doesn't use self and is defined inside class -# it should be called on an instance or changed to static method. -# In its current definition it behaves like a regular method but is missing 'self'. -# Actually it is defined as def cycle_check(node): which means it takes one arg. -# If called as LinkedListNode.cycle_check(a) it should work if it was just a function. - -print(a.cycle_check()) +if __name__ == "__main__": + # Create a Linked List + a = LinkedListNode(1) + b = LinkedListNode(2) + c = LinkedListNode(3) + + # Create a cycle + a.nextnode = b + b.nextnode = c + c.nextnode = a + + print(f"Node A value: {a.value}") + print(f"Node B value: {b.value}") + print(f"Node C value: {c.value}") + + print(f"Cycle detected: {a.cycle_check()}") + + # Break the cycle and test again + c.nextnode = None + print(f"Cycle detected after breaking: {a.cycle_check()}") diff --git a/LinkedLists/SingleLinkedListImple.py b/LinkedLists/SinglyLinkedListImple.py similarity index 100% rename from LinkedLists/SingleLinkedListImple.py rename to LinkedLists/SinglyLinkedListImple.py diff --git a/Queues/README.md b/Queues/README.md index a1c90d0..1c7c40a 100644 --- a/Queues/README.md +++ b/Queues/README.md @@ -4,5 +4,5 @@ This directory contains Python implementations of the Queue data structure. ## Contents -- [Queue Implementation](QueueImple.py): Basic implementation of a FIFO (First-In-First-Out) queue using a Python list. Includes `enqueue`, `dequeue`, `isEmpty`, and `size` methods. -- [Queue with Two Stacks](QueueWith2StacksImple.py): Implements a queue using two stacks (represented by Python lists) to achieve FIFO behavior. +- [Queue Implementation](QueueImple.py): Basic implementation of a FIFO (First-In-First-Out) queue. Time Complexity: $O(n)$ for enqueue, $O(1)$ for dequeue. +- [Queue with Two Stacks](QueueWith2StacksImple.py): Implements a queue using two stacks. Time Complexity: $O(1)$ amortized for both operations. diff --git a/README.md b/README.md index b8de7d5..768bc1c 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,7 @@ Most scripts in this repository are standalone and can be executed directly: ```bash # Run any Python script -python3 Arrays/Anagram_Check_Sorted_Sol.py +python3 Arrays/AnagramCheckSortedSol.py # Or run from the repo root python3 Sorting/BubbleSortImple.py @@ -80,7 +80,8 @@ python3 Sorting/BubbleSortImple.py ``` . β”œβ”€β”€ Arrays/ # πŸ”€ Array-based problems and algorithms -β”œβ”€β”€ Error-debug/ # ⚠️ Error handling and debugging examples +β”œβ”€β”€ Deque/ # πŸ”„ Double-ended queue +β”œβ”€β”€ ErrorHandling/ # ⚠️ Error handling and debugging examples β”œβ”€β”€ GraphAlgorithms/ # πŸ—ΊοΈ Graph traversal (BFS, DFS) and pathfinding β”œβ”€β”€ LinkedLists/ # πŸ”— Singly and Doubly Linked Lists β”œβ”€β”€ Queues/ # πŸ“¦ Queue implementations (FIFO) @@ -88,7 +89,6 @@ python3 Sorting/BubbleSortImple.py β”œβ”€β”€ Sorting/ # πŸ“Š Common sorting algorithms β”œβ”€β”€ Stacks/ # πŸ“š Stack implementations and applications β”œβ”€β”€ Trees/ # 🌳 Binary Trees, BSTs, Heaps, and Traversals -β”œβ”€β”€ deque/ # πŸ”„ Double-ended queue β”œβ”€β”€ CONTRIBUTING.md # 🀝 Contribution guidelines β”œβ”€β”€ LICENSE # πŸ“„ MIT License └── README.md # πŸ“– This file @@ -98,42 +98,42 @@ python3 Sorting/BubbleSortImple.py ## πŸ“Š Data Structures -### Arrays πŸ”€ +### Arrays πŸ”’ Common array-based algorithms and manipulations. -- [Anagram Check](Arrays/): [Sorted](Arrays/Anagram_Check_Sorted_Sol.py) & [Manual](Arrays/Anagram_Check_manual_Sol.py) solutions -- [Array Pair Sum](Arrays/ArrayPairSumSol.py): Find pairs that sum to $k$ -- [Find Missing Element](Arrays/): [XOR](Arrays/ArrayFindTheMissingElement_XOR_sol.py), [Brute Force](Arrays/ArrayFindTheMissingElement_brute_force_sol.py), [Hash Table](Arrays/ArrayFindTheMissingElement_hash_table_sol.py), & [Sum](Arrays/ArrayFindTheMissingElement_takingSumandSubtract_sol.py) approaches +- [Anagram Check](Arrays/): [Sorted](Arrays/AnagramCheckSortedSol.py) & [Manual](Arrays/AnagramCheckManualSol.py) solutions +- [Array Pair Sum](Arrays/ArrayPairSumSol.py): Find pairs that sum to $k$ ($O(n)$) +- [Find Missing Element](Arrays/): [XOR](Arrays/ArrayFindTheMissingElementXORSol.py), [Brute Force](Arrays/ArrayFindTheMissingElementBruteForceSol.py), [Hash Table](Arrays/ArrayFindTheMissingElementHashTableSol.py), & [Sum](Arrays/ArrayFindTheMissingElementSumSol.py) approaches ### Linked Lists πŸ”— Implementations and problems involving linked structures. -- [Singly Linked List](LinkedLists/SingleLinkedListImple.py) & [Doubly Linked List](LinkedLists/DoublyLinkedListImple.py) -- [Cycle Detection](LinkedLists/SinglyLinkedListCycleCheckImple.py): Detect cycles using two pointers (Floyd's algorithm) -- [Reverse Linked List](LinkedLists/LinkedListReversal.py): In-place reversal -- [Nth to Last Node](LinkedLists/LinkedListNthToLastNode.py): Find the $n$-th node from the end +- [Singly Linked List](LinkedLists/SinglyLinkedListImple.py) & [Doubly Linked List](LinkedLists/DoublyLinkedListImple.py) +- [Cycle Detection](LinkedLists/SinglyLinkedListCycleCheckImple.py): Detect cycles using Floyd's algorithm ($O(n)$) +- [Reverse Linked List](LinkedLists/LinkedListReversal.py): In-place reversal ($O(n)$) +- [Nth to Last Node](LinkedLists/LinkedListNthToLastNode.py): Find the $n$-th node from the end ($O(n)$) ### Stacks πŸ“š LIFO (Last-In-First-Out) data structures. -- [Stack Implementation](Stacks/StackImple.py): Basic operations (push, pop, peek) -- [Balanced Parentheses](Stacks/BalanceParenthlessCheckImple.py): Check for balanced brackets using a stack +- [Stack Implementation](Stacks/StackImple.py): Basic operations ($O(1)$ push, pop) +- [Balanced Parentheses](Stacks/BalanceParenthesesCheckImple.py): Check for balanced brackets using a stack ($O(n)$) ### Queues πŸ“¦ FIFO (First-In-First-Out) data structures. -- [Queue Implementation](Queues/QueueImple.py): Basic operations (enqueue, dequeue) -- [Queue with Two Stacks](Queues/QueueWith2StacksImple.py): Implementing FIFO using LIFO structures +- [Queue Implementation](Queues/QueueImple.py): Basic operations ($O(n)$ enqueue, $O(1)$ dequeue) +- [Queue with Two Stacks](Queues/QueueWith2StacksImple.py): Implementing FIFO using LIFO structures ($O(1)$ amortized) ### Deque πŸ”„ Double-ended queue operations. -- [Deque Implementation](deque/DequeImple.py): Operations at both ends +- [Deque Implementation](Deque/DequeImple.py): Operations at both ends ($O(1)$ front, $O(n)$ rear) ### Trees 🌳 Hierarchical data structures. -- [Binary Search Tree](Trees/BinarySearchTreesImple.py): Complete BST implementation +- [Binary Search Tree](Trees/BinarySearchTreesImple.py): Complete BST implementation ($O(\log n)$ average) - [BST Validation](Trees/): [Solution 1 (In-order)](Trees/BinarySearchTreeCheckImpleSol1.py) & [Solution 2 (Range check)](Trees/BinarySearchTreeCheckImpleSol2.py) -- [Binary Search](Trees/): [Iterative](Trees/BinarySearchImple.py) & [Recursive](Trees/BinarySearchRecursiveImple.py) -- [Binary Heap](Trees/BinaryHeapImple.py): Min-heap implementation -- [Tree Traversals](Trees/TreeLevelOrderPrintImple.py): Level order (BFS) printing -- [Trim BST](Trees/TrimBinarySearchTreeImple.py): Keep nodes within a range -- [Tree Representations](Trees/): [Nodes & References](Trees/TreeRepresentationWithNodesReferences.py) & [List of Lists](Trees/buildTreeTest.py) +- [Binary Search](Trees/): [Iterative](Trees/BinarySearchImple.py) & [Recursive](Trees/BinarySearchRecursiveImple.py) ($O(\log n)$) +- [Binary Heap](Trees/BinaryHeapImple.py): Min-heap implementation ($O(\log n)$) +- [Tree Traversals](Trees/TreeLevelOrderPrintImple.py): Level order (BFS) printing ($O(n)$) +- [Trim BST](Trees/TrimBinarySearchTreeImple.py): Keep nodes within a range ($O(n)$) +- [Tree Representations](Trees/): [Nodes & References](Trees/TreeRepresentationWithNodesReferences.py) & [List of Lists](Trees/BuildTreeTest.py) --- @@ -144,31 +144,31 @@ Algorithms for arranging elements in order. - [Bubble Sort](Sorting/BubbleSortImple.py) - $O(n^2)$ - [Selection Sort](Sorting/SelectionSortImple.py) - $O(n^2)$ - [Insertion Sort](Sorting/InsertionSortImple.py) - $O(n^2)$ -- [Shell Sort](Sorting/ShellSortImple.py) - $O(n \log n)$ +- [Shell Sort](Sorting/ShellSortImple.py) - $O(n^2)$ (worst case) - [Merge Sort](Sorting/MergeSortImple.py) - $O(n \log n)$ - [Quick Sort](Sorting/QuickSortImple.py) - $O(n \log n)$ average ### Recursion & Dynamic Programming πŸ”€ Solving problems by breaking them into smaller sub-problems. -- [Fibonacci Sequence](Recursion/): [Iterative](Recursion/FibonacciSeqIterative.py), [Recursive](Recursion/FibonacciSeqRecursion.py), & [Dynamic Programming](Recursion/FibonacciSeqDynamic.py) -- [Coin Change Problem](Recursion/): [Recursive](Recursion/CoinChangeProblemRecursion.py) & [Dynamic Programming](Recursion/CoinChangeProblemDynamic.py) -- [String Operations](Recursion/): [Reverse](Recursion/RecursionReverseStr.py) & [Permutations](Recursion/RecursionStrPermutation.py) -- [Math Operations](Recursion/): [Cumulative Sum](Recursion/RecursionCumulativeSum.py) & [Sum of Digits](Recursion/RecursionSumOfDigits.py) -- [Word Split](Recursion/RecursionWordSplit.py): Dynamic Programming solution +- [Fibonacci Sequence](Recursion/): [Iterative](Recursion/FibonacciSeqIterative.py) ($O(n)$), [Recursive](Recursion/FibonacciSeqRecursion.py) ($O(2^n)$), & [Dynamic Programming](Recursion/FibonacciSeqDynamic.py) ($O(n)$) +- [Coin Change Problem](Recursion/): [Recursive](Recursion/CoinChangeProblemRecursion.py) & [Dynamic Programming](Recursion/CoinChangeProblemDynamic.py) ($O(n \cdot m)$) +- [String Operations](Recursion/): [Reverse](Recursion/RecursionReverseStr.py) ($O(n)$) & [Permutations](Recursion/RecursionStrPermutation.py) ($O(n!)$) +- [Math Operations](Recursion/): [Cumulative Sum](Recursion/RecursionCumulativeSum.py) ($O(n)$) & [Sum of Digits](Recursion/RecursionSumOfDigits.py) ($O(\log_{10} n)$) +- [Word Split](Recursion/RecursionWordSplit.py): Dynamic Programming solution ($O(n^2)$) ### Graph Algorithms πŸ—ΊοΈ Algorithms for graph traversal and pathfinding. -- [Adjacency List](GraphAlgorithms/AdjacencyListGraphImple.py): Graph ADT implementation -- [Breadth First Search (BFS)](GraphAlgorithms/BFS.py): Word Ladder problem -- [Depth First Search (DFS)](GraphAlgorithms/DFSGeneral.py): General DFS implementation -- [Knight's Tour Problem](GraphAlgorithms/): [Graph Generation](GraphAlgorithms/TheKnightsTourProblem.py) & [DFS Solution](GraphAlgorithms/DFSImpleTheKnightsTourProblem.py) +- [Adjacency List](GraphAlgorithms/AdjacencyListGraphImple.py): Graph ADT implementation ($O(V+E)$) +- [Breadth First Search (BFS)](GraphAlgorithms/BFS.py): Word Ladder problem ($O(V+E)$) +- [Depth First Search (DFS)](GraphAlgorithms/DFSGeneral.py): General DFS implementation ($O(V+E)$) +- [Knight's Tour Problem](GraphAlgorithms/): [Graph Generation](GraphAlgorithms/TheKnightsTourProblem.py) & [DFS Solution](GraphAlgorithms/DFSImpleTheKnightsTourProblem.py) ($O(k^N)$) - [Word Ladder Problem](GraphAlgorithms/WordLadderProblem.py): Building the word ladder graph --- ## ⚠️ Error Handling & Debugging -- [Error and Exceptions](Error-debug/ErrorExceptions.py): Demonstrates `try`, `except`, `else`, and `finally` blocks for robust error handling. +- [Error and Exceptions](ErrorHandling/ErrorExceptions.py): Demonstrates `try`, `except`, `else`, and `finally` blocks for robust error handling. --- diff --git a/Recursion/FibonacciSeqDynamic.py b/Recursion/FibonacciSeqDynamic.py index b16783e..6d81b6c 100644 --- a/Recursion/FibonacciSeqDynamic.py +++ b/Recursion/FibonacciSeqDynamic.py @@ -2,26 +2,36 @@ # memoization + recursion = dynamic programming # Author: Pradeep K. Pant, ppant@cpan.org -# Instantiate Cache information -n = 10 -cache = [None] * (n + 1) - # Implement fibonacci_dynamic -def fibonacci_dynamic(n): +def fibonacci_dynamic(n, cache=None): + """ + Finds the n-th Fibonacci number using dynamic programming (memoization). + :param n: The position in the Fibonacci sequence. + :param cache: Optional cache dictionary for memoization. + :return: The n-th Fibonacci number. + """ + if cache is None: + cache = {} + # Base Case if n == 0 or n == 1: return n - # Check cache if already val of n present if yes pick from there this will save time - if cache[n] != None: + # Check cache if already val of n present + if n in cache: return cache[n] # Recursive call to and keep setting cache - cache[n] = fibonacci_dynamic(n - 1) + fibonacci_dynamic(n - 2) + cache[n] = fibonacci_dynamic(n - 1, cache) + fibonacci_dynamic(n - 2, cache) return cache[n] # Test -# We'll try to find the 9th no in the fibnacci sequence which is 34 -print (fibonacci_dynamic(9)) -# 0, 1, 1, 2, 3, 5, 8, 13, 21, 34 -# The recursive-memoization solution is exponential time Big-O , with O(n) +if __name__ == "__main__": + # We'll try to find the 9th no in the fibonacci sequence which is 34 + # 0, 1, 1, 2, 3, 5, 8, 13, 21, 34 + n_test = 9 + print(f"The {n_test}th Fibonacci number is: {fibonacci_dynamic(n_test)}") + + # Large value to test performance and avoidance of fixed-size global cache + n_large = 50 + print(f"The {n_large}th Fibonacci number is: {fibonacci_dynamic(n_large)}") diff --git a/Recursion/README.md b/Recursion/README.md index 7265340..3fdfb9e 100644 --- a/Recursion/README.md +++ b/Recursion/README.md @@ -1,21 +1,21 @@ -# Recursion +# Recursion and Dynamic Programming This directory contains Python implementations of problems solved using recursion and dynamic programming. ## Contents ### Fibonacci Sequence -- [Fibonacci (Iterative)](FibonacciSeqIterative.py): Iterative implementation of the Fibonacci sequence. -- [Fibonacci (Recursive)](FibonacciSeqRecursion.py): Simple recursive implementation of the Fibonacci sequence. -- [Fibonacci (Dynamic Programming)](FibonacciSeqDynamic.py): Optimized Fibonacci sequence using memoization. +- [Fibonacci (Iterative)](FibonacciSeqIterative.py): Iterative implementation of the Fibonacci sequence. Time Complexity: $O(n)$ +- [Fibonacci (Recursive)](FibonacciSeqRecursion.py): Simple recursive implementation. Time Complexity: $O(2^n)$ +- [Fibonacci (Dynamic Programming)](FibonacciSeqDynamic.py): Optimized Fibonacci sequence using memoization. Time Complexity: $O(n)$ ### Coin Change Problem -- [Coin Change (Recursive)](CoinChangeProblemRecursion.py): Basic recursive solution to find the minimum number of coins for change. -- [Coin Change (Dynamic Programming)](CoinChangeProblemDynamic.py): Optimized solution to the coin change problem using dynamic programming. +- [Coin Change (Recursive)](CoinChangeProblemRecursion.py): Basic recursive solution. Time Complexity: Exponential. +- [Coin Change (Dynamic Programming)](CoinChangeProblemDynamic.py): Optimized solution using dynamic programming. Time Complexity: $O(n \cdot m)$ ### Other Recursive Problems -- [Cumulative Sum](RecursionCumulativeSum.py): Computes the cumulative sum from 0 to $n$ recursively. -- [Reverse a String](RecursionReverseStr.py): Reverses a string using recursive calls. -- [String Permutations](RecursionStrPermutation.py): Generates all possible permutations of a given string. -- [Sum of Digits](RecursionSumOfDigits.py): Calculates the sum of all individual digits in an integer recursively. -- [Word Split](RecursionWordSplit.py): Determines if a string can be split into words from a given list. +- [Cumulative Sum](RecursionCumulativeSum.py): Computes the cumulative sum from 0 to $n$ recursively. Time Complexity: $O(n)$ +- [Reverse a String](RecursionReverseStr.py): Reverses a string using recursion. Time Complexity: $O(n)$ +- [String Permutations](RecursionStrPermutation.py): Generates all permutations of a string. Time Complexity: $O(n!)$ +- [Sum of Digits](RecursionSumOfDigits.py): Calculates the sum of digits in an integer recursively. Time Complexity: $O(\log_{10} n)$ +- [Word Split](RecursionWordSplit.py): Determines if a string can be split into words from a list. Time Complexity: $O(n^2)$ diff --git a/Sorting/README.md b/Sorting/README.md index 0b76399..bcd136a 100644 --- a/Sorting/README.md +++ b/Sorting/README.md @@ -4,9 +4,9 @@ This directory contains Python implementations of various sorting algorithms wit ## Contents -- [Bubble Sort](BubbleSortImple.py): Implementation of Bubble Sort with $O(n^2)$ complexity. -- [Selection Sort](SelectionSortImple.py): Implementation of Selection Sort, improving on Bubble Sort by making only one exchange per pass. -- [Insertion Sort](InsertionSortImple.py): Implementation of Insertion Sort, maintaining a sorted sublist. -- [Shell Sort](ShellSortImple.py): Implementation of Shell Sort (diminishing increment sort), improving on Insertion Sort. -- [Merge Sort](MergeSortImple.py): A recursive "divide and conquer" algorithm with $O(n \log n)$ complexity. -- [Quick Sort](QuickSortImple.py): Implementation of Quick Sort (partition exchange sort), using divide and conquer in-place. +- [Bubble Sort](BubbleSortImple.py): Implementation of Bubble Sort. Time Complexity: $O(n^2)$ +- [Selection Sort](SelectionSortImple.py): Implementation of Selection Sort. Time Complexity: $O(n^2)$ +- [Insertion Sort](InsertionSortImple.py): Implementation of Insertion Sort. Time Complexity: $O(n^2)$ +- [Shell Sort](ShellSortImple.py): Implementation of Shell Sort (diminishing increment sort). Time Complexity: $O(n^2)$ (worst case) +- [Merge Sort](MergeSortImple.py): A recursive "divide and conquer" algorithm. Time Complexity: $O(n \log n)$ +- [Quick Sort](QuickSortImple.py): Implementation of Quick Sort (partition exchange sort). Time Complexity: $O(n \log n)$ average. diff --git a/Stacks/BalanceParenthlessCheckImple.py b/Stacks/BalanceParenthesesCheckImple.py similarity index 100% rename from Stacks/BalanceParenthlessCheckImple.py rename to Stacks/BalanceParenthesesCheckImple.py diff --git a/Stacks/README.md b/Stacks/README.md index e799a74..d9cbb5c 100644 --- a/Stacks/README.md +++ b/Stacks/README.md @@ -4,5 +4,5 @@ This directory contains Python implementations of the Stack data structure and i ## Contents -- [Stack Implementation](StackImple.py): Basic implementation of a LIFO (Last-In-First-Out) stack using a Python list. Includes `push`, `pop`, `peek`, `isEmpty`, and `size` methods. -- [Balanced Parentheses Check](BalanceParenthlessCheckImple.py): Uses a stack to check if a string of opening and closing parentheses (round, square, and curly) is balanced. +- [Stack Implementation](StackImple.py): Basic implementation of a LIFO (Last-In-First-Out) stack using a Python list. Time Complexity: $O(1)$ for push and pop. +- [Balanced Parentheses Check](BalanceParenthesesCheckImple.py): Uses a stack to check if a string of parentheses is balanced. Time Complexity: $O(n)$ diff --git a/Trees/buildTreeTest.py b/Trees/BuildTreeTest.py similarity index 100% rename from Trees/buildTreeTest.py rename to Trees/BuildTreeTest.py diff --git a/Trees/README.md b/Trees/README.md index 2047225..ed312b1 100644 --- a/Trees/README.md +++ b/Trees/README.md @@ -1,23 +1,16 @@ # Trees -This directory contains Python implementations of various tree-based data structures and algorithms. +This directory contains Python implementations of tree-based data structures and algorithms. ## Contents -### Binary Search Trees (BST) -- [Binary Search Tree Implementation](BinarySearchTreesImple.py): A comprehensive implementation of a BST with `TreeNode` and `BinarySearchTree` classes, including insertion, deletion, and search. -- [Validate BST (Solution 1)](BinarySearchTreeCheckImpleSol1.py): Validates a BST by performing an in-order traversal and checking if the resulting values are sorted. -- [Validate BST (Solution 2)](BinarySearchTreeCheckImpleSol2.py): Validates a BST by keeping track of the minimum and maximum allowable values for each node. -- [Trim a BST](TrimBinarySearchTreeImple.py): Trims a BST so that all node values fall within a specified range $[min, max]$. - -### Search Algorithms -- [Binary Search (Iterative)](BinarySearchImple.py): Iterative implementation of the binary search algorithm on a sorted list. -- [Binary Search (Recursive)](BinarySearchRecursiveImple.py): Recursive implementation of the binary search algorithm. - -### Heaps -- [Binary Heap Implementation](BinaryHeapImple.py): Implements a min-heap using a recursive approach, including `insert`, `delMin`, and `buildHeap`. - -### Tree Representations & Traversals -- [Nodes and References Representation](TreeRepresentationWithNodesReferences.py): A simple implementation of a binary tree using a class-based nodes and references approach. -- [List of Lists Representation](buildTreeTest.py): Demonstrates building and manipulating a tree using a "list of lists" approach. -- [Tree Level Order Print](TreeLevelOrderPrintImple.py): Prints a binary tree in level order (breadth-first) using a queue, with each level on a new line. +- [Binary Search Tree Implementation](BinarySearchTreesImple.py): Complete BST implementation. Time Complexity: $O(\log n)$ average, $O(n)$ worst case. +- [Binary Search Tree Check (Solution 1)](BinarySearchTreeCheckImpleSol1.py): Validates a BST using in-order traversal. Time Complexity: $O(n)$ +- [Binary Search Tree Check (Solution 2)](BinarySearchTreeCheckImpleSol2.py): Validates a BST using range checks. Time Complexity: $O(n)$ +- [Binary Search (Iterative)](BinarySearchImple.py): Iterative implementation of binary search. Time Complexity: $O(\log n)$ +- [Binary Search (Recursive)](BinarySearchRecursiveImple.py): Recursive implementation of binary search. Time Complexity: $O(\log n)$ +- [Binary Heap Implementation](BinaryHeapImple.py): Min-heap implementation. Time Complexity: $O(\log n)$ for insert and extract-min. +- [Tree Level Order Print](TreeLevelOrderPrintImple.py): BFS-based level order traversal. Time Complexity: $O(n)$ +- [Trim a Binary Search Tree](TrimBinarySearchTreeImple.py): Trims a BST within a given range. Time Complexity: $O(n)$ +- [Tree Representation (Nodes and References)](TreeRepresentationWithNodesReferences.py): Basic tree structure using nodes. +- [Build Tree Test](BuildTreeTest.py): Tree implementation using a list of lists.