diff --git a/Exercise_1.py b/Exercise_1.py index 3e6adcf4..4ef235b0 100644 --- a/Exercise_1.py +++ b/Exercise_1.py @@ -5,8 +5,19 @@ # if present, else returns -1 def binarySearch(arr, l, r, x): - #write your code here - + # write your code here + # tc O(log n), sc O(1). + left, right = 0, len(nums) - 1 + + while left <= right: + mid = left + ((right - left) // 2) + if nums[mid] == target: + return mid + if nums[mid] > target: + right = mid - 1 + else: + left = mid + 1 + return -1 # Test array diff --git a/Exercise_2.py b/Exercise_2.py index 35abf0dd..7c65f9a7 100644 --- a/Exercise_2.py +++ b/Exercise_2.py @@ -1,16 +1,35 @@ # Python program for implementation of Quicksort Sort -# give you explanation for the approach -def partition(arr,low,high): - - - #write your code here - - -# Function to do Quick sort -def quickSort(arr,low,high): +# tc O(n log n), sc O(log n), but in worst case tc O(n^2) and sc O(n). +# the worst case tc and sc can be reduced by selecting middle element as pivot. +def partition(start, end): + import random + random_idx = random.randint(start, end) + arr[random_idx], arr[start] = arr[start], arr[random_idx] - #write your code here + left, right = start + 1, end + + while left <= right: + if arr[left] <= arr[start]: + left += 1 + elif arr[right] > arr[start]: + right -= 1 + else: + arr[left], arr[right] = arr[right], arr[left] + left += 1 + right -= 1 + + arr[start], arr[right] = arr[right], arr[start] + return right + + +def quickSort(arr, start, end): + if start >= end: + return + pivot_idx = partition(start, end) + quick(start, pivot_idx - 1) + quick(pivot_idx + 1, end) + # Driver code to test above arr = [10, 7, 8, 9, 1, 5] diff --git a/Exercise_3.py b/Exercise_3.py index a26a69b8..5333746e 100644 --- a/Exercise_3.py +++ b/Exercise_3.py @@ -2,19 +2,33 @@ class Node: # Function to initialise the node object - def __init__(self, data): + def __init__(self, data): + self.val = data + self.next = None class LinkedList: def __init__(self): - + self.head = None + self.tail = None def push(self, new_data): - + if not self.head: + self.head = Node(new_data) + self.tail = self.head + else: + self.tail.next = Node(new_data) + self.tail = self.tail.next # Function to get the middle of # the linked list - def printMiddle(self): + def printMiddle(self): + # tc O(n), sc O(1). + slow, fast = head, head + while fast and fast.next: + fast = fast.next.next + slow = slow.next + return slow # Driver code list1 = LinkedList() diff --git a/Exercise_4.py b/Exercise_4.py index 9bc25d3d..f166556b 100644 --- a/Exercise_4.py +++ b/Exercise_4.py @@ -1,12 +1,49 @@ # Python program for implementation of MergeSort def mergeSort(arr): - #write your code here + # write your code here + # tc O(n log n), sc O(n + log n = n). + def divide_and_conquer(array, start, end): + if start >= end: + return + + mid = start + ((end - start) // 2) + divide_and_conquer(start, mid) + divide_and_conquer(mid+1, end) + + # merge two sorted arrays + sorted_arrays = [] + i, j = start, mid+1 + + while i <= mid and j <= end: + if array[i] <= array[j]: + sorted_arrays.append(array[i]) + i += 1 + else: + sorted_arrays.append(array[j]) + j += 1 + + while i <= mid: + sorted_arrays.append(array[i]) + i += 1 + + while j <= end: + sorted_arrays.append(array[j]) + j += 1 + + array[start:end+1] = sorted_arrays + + divide_and_conquer(arr, 0, len(arr)-1) # Code to print the list def printList(arr): - #write your code here + # write your code here + sortedlist = [] + for num in arr: + sortedlist.append(num) + + print(sortedlist) # driver code to test the above code if __name__ == '__main__': diff --git a/Exercise_5.py b/Exercise_5.py index 1da24ffb..94cb4304 100644 --- a/Exercise_5.py +++ b/Exercise_5.py @@ -1,10 +1,37 @@ # Python program for implementation of Quicksort -# This function is same in both iterative and recursive -def partition(arr, l, h): - #write your code here +def random_partition(arr, low, high): + # Swapping arr[high] with any random element in the array and then partitioning around + # pivot_element = arr[high]. + import random + random_index = random.randint(low, high) + arr[random_index], arr[high] = arr[high], arr[random_index] + pivot = low + pivot_element = arr[high] -def quickSortIterative(arr, l, h): - #write your code here + for i in range(low, high): + if arr[i] < pivot_element: + arr[i], arr[pivot] = arr[pivot], arr[i] + pivot += 1 + + # Taking pivot_element to pivot position. + arr[pivot], arr[high] = arr[high], arr[pivot] + return pivot + +def quick_sort(arr): + n = len(arr) + helper = [(0, n - 1)] + + while helper: + low, high = helper.pop() + + pivot = random_partition(arr, low, high) + + if pivot - 1 > low: + helper.append((low, pivot - 1)) + if pivot + 1 < high: + helper.append((pivot + 1, high)) + + return arr