diff --git a/Exercise_1.py b/Exercise_1.py index 3e6adcf4..f509c4ef 100644 --- a/Exercise_1.py +++ b/Exercise_1.py @@ -1,13 +1,28 @@ -# Python code to implement iterative Binary -# Search. - -# It returns location of x in given array arr -# if present, else returns -1 +# Time Complexity: O(log n) +# Space Complexity: O(1) + +# Did this code successfully run on LeetCode: Yes + +# Any problem you faced while coding this: No major issues + +# Approach: +# Binary search works only on a sorted array +# Compare the target with the middle element +# If they match, return the middle index +# If the target is greater, search the right half +# If the target is smaller, search the left half + def binarySearch(arr, l, r, x): - - #write your code here - - + while (l <= r): + m = (l + r) // 2 + if (arr[m] == x): + return m + elif (arr[m] < x): + l = m + 1 + else: + r = m -1 + + return -1 # Test array arr = [ 2, 3, 4, 10, 40 ] @@ -17,6 +32,6 @@ def binarySearch(arr, l, r, x): result = binarySearch(arr, 0, len(arr)-1, x) if result != -1: - print "Element is present at index % d" % result + print("Element is present at index %d" % result) else: - print "Element is not present in array" + print("Element is not present in array") diff --git a/Exercise_2.py b/Exercise_2.py index 35abf0dd..2a786c24 100644 --- a/Exercise_2.py +++ b/Exercise_2.py @@ -1,16 +1,42 @@ -# Python program for implementation of Quicksort Sort - -# give you explanation for the approach +# Time Complexity: +# Average Case: O(n log n) +# Worst Case: O(n^2) + +# Space Complexity: +# Average Case: O(log n) +# Worst Case: O(n) + +# Did this code successfully run on LeetCode: Not directly applicable because LeetCode uses a different function format + +# Any problem you faced while coding this: The main challenge was placing the pivot in its correct position and using the correct recursive boundaries + +# Approach: +# 1. Select the final element as the pivot +# 2. Move all elements smaller than or equal to the pivot to its left +# 3. Move all elements greater than the pivot to its right +# 4. Return the pivot's final index +# 5. Recursively sort the left and right parts of the array + + def partition(arr,low,high): - - - #write your code here + pivot = arr[high] + i = low - 1 + + for j in range(low, high): + if arr[j] <= pivot: + i += 1 + arr[i], arr[j] = arr[j], arr[i] + + arr[i + 1], arr[high] = arr[high], arr[i + 1] + return i + 1 # Function to do Quick sort def quickSort(arr,low,high): - - #write your code here + if low < high: + pi = partition(arr, low, high) + quickSort(arr, low, pi - 1) + quickSort(arr, pi + 1, high) # Driver code to test above arr = [10, 7, 8, 9, 1, 5] diff --git a/Exercise_3.py b/Exercise_3.py index a26a69b8..529c516d 100644 --- a/Exercise_3.py +++ b/Exercise_3.py @@ -1,20 +1,48 @@ -# Node class +# Time Complexity: +# push: O(1) +# printMiddle: O(n) + +# Space Complexity: +# O(n) total space for storing n nodes +# O(1) extra space for printMiddle + +# Did this code successfully run on LeetCode: Yes + +# Any problem you faced while coding this: no major issues + +# Approach: +# Use two pointers: slow moves one node at a time, fast moves two nodes at a time +# When fast reaches the end, slow will be at the middle node + + class Node: # Function to initialise the node object def __init__(self, data): + self.data = data + self.next = None class LinkedList: def __init__(self): - + self.head = None def push(self, new_data): + new_node = Node(new_data) + new_node.next = self.head + self.head = new_node - # Function to get the middle of # the linked list def printMiddle(self): + slow_ptr = self.head + fast_ptr = self.head + + if self.head is not None: + while (fast_ptr is not None and fast_ptr.next is not None): + fast_ptr = fast_ptr.next.next + slow_ptr = slow_ptr.next + print("The middle element is:", slow_ptr.data) # Driver code list1 = LinkedList() diff --git a/Exercise_4.py b/Exercise_4.py index 9bc25d3d..6204bcd2 100644 --- a/Exercise_4.py +++ b/Exercise_4.py @@ -1,12 +1,53 @@ -# Python program for implementation of MergeSort +# Time Complexity: O(n log n) +# Space Complexity: O(n) + +# Did this code successfully run on LeetCode: Not directly applicable because LeetCode uses a different function format + +# Any problem you faced while coding this: The main challenge was correctly merging the two sorted halves and copying any remaining elements + +# Approach: +# 1. Divide the array into two halves +# 2. Recursively sort the left half +# 3. Recursively sort the right half +# 4. Merge the two sorted halves back into the original array + def mergeSort(arr): + if len(arr) > 1: + mid = len(arr) // 2 + L = arr[:mid] + R = arr[mid:] + + mergeSort(L) + mergeSort(R) + + i = j = k = 0 + + while i < len(L) and j < len(R): + if L[i] <= R[j]: + arr[k] = L[i] + i += 1 + else: + arr[k] = R[j] + j += 1 + k += 1 + + while i < len(L): + arr[k] = L[i] + i += 1 + k += 1 + + while j < len(R): + arr[k] = R[j] + j += 1 + k += 1 - #write your code here # Code to print the list def printList(arr): - - #write your code here + for i in range(len(arr)): + print(arr[i], end=" ") + print() + # driver code to test the above code if __name__ == '__main__': diff --git a/Exercise_5.py b/Exercise_5.py index 1da24ffb..e20d0732 100644 --- a/Exercise_5.py +++ b/Exercise_5.py @@ -1,10 +1,62 @@ -# Python program for implementation of Quicksort +# Time Complexity: +# Average Case: O(n log n) +# Worst Case: O(n^2) + +# Space Complexity: +# Average Case: O(log n) +# Worst Case: O(n) + +# Did this code successfully run on LeetCode: Not directly applicable because LeetCode uses a different function format + +# Any problem you faced while coding this: The main challenge was correctly storing and processing the left and right subarray boundaries using a stack instead of recursion + +# Approach: +# 1. Store the initial low and high indices in a stack +# 2. Remove one range from the stack +# 3. Partition that range and place the pivot in its correct position +# 4. Add the left and right unsorted ranges to the stack +# 5. Continue until the stack is empty # This function is same in both iterative and recursive def partition(arr, l, h): - #write your code here + pivot = arr[h] + i = l - 1 + + for j in range(l, h): + if arr[j] <= pivot: + i += 1 + arr[i], arr[j] = arr[j], arr[i] + + arr[i + 1], arr[h] = arr[h], arr[i + 1] + return i + 1 def quickSortIterative(arr, l, h): - #write your code here + stack = [(l, h)] + + while stack: + low, high = stack.pop() + + if low < high: + pivot_index = partition(arr, low, high) + + stack.append((low, pivot_index - 1)) + stack.append((pivot_index + 1, high)) + +if __name__ == "__main__": + test_cases = [ + [10, 7, 8, 9, 1, 5], + [1, 2, 3, 4, 5], + [5, 4, 3, 2, 1], + [4, 2, 4, 1, 2], + [7], + [], + ] + for arr in test_cases: + expected = sorted(arr) + quickSortIterative(arr, 0, len(arr) - 1) + print("Sorted:", arr) + print("Expected:", expected) + print("Passed:", arr == expected) + print()