diff --git a/.Rhistory b/.Rhistory new file mode 100644 index 00000000..e69de29b diff --git a/Exercise_1.py b/Exercise_1.py index 3e6adcf4..33067a82 100644 --- a/Exercise_1.py +++ b/Exercise_1.py @@ -3,20 +3,49 @@ # It returns location of x in given array arr # if present, else returns -1 + +# Time Complexity : O(log n) +# - In each recursive call, the search space is reduced by half. +# Space Complexity : O(log n) +# - Due to recursion stack. Each recursive call adds a frame to the stack. +# Did this code successfully run on Leetcode : NA +# Any problem you faced while coding this : NA + def binarySearch(arr, l, r, x): - #write your code here - + # low and high represent the current portion of the array we are looking at + low = l + high = r + + # if the current search space is valid + if low <= high: + # find the middle element + mid = low + (high - low) // 2 + + # if the middle element is what we are looking for, return its index + if arr[mid] == x: + return mid + + # if x is bigger than the middle, search in the right half + if arr[mid] < x: + return binarySearch(arr, mid + 1, high, x) + + # if x is smaller than the middle, search in the left half + if arr[mid] > x: + return binarySearch(arr, low, mid - 1, x) + else: + # if we reach here, the element is not in the array + return -1 # Test array arr = [ 2, 3, 4, 10, 40 ] -x = 10 +x = 2 # Function call 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..dd27704f 100644 --- a/Exercise_2.py +++ b/Exercise_2.py @@ -1,16 +1,43 @@ # 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): - - #write your code here +# Time Complexity : O(n log n) +# Space Complexity : O(log n) due to recursion stack +# Did this code successfully run on Leetcode : NA +# Any problem you faced while coding this : NA + +def partition(arr, low, high): + """ + This function takes the last element as pivot, + places the pivot at its correct position in sorted array, + and puts smaller elements before it and larger after it. + """ + i = low - 1 # index of smaller element + pivot = arr[high] # choose the last element as pivot + + # go through all elements and swap if smaller than pivot + for j in range(low, high): + if arr[j] < pivot: + i += 1 + arr[i], arr[j] = arr[j], arr[i] # swap + + # put pivot in the correct position + arr[i + 1], arr[high] = arr[high], arr[i + 1] + return i + 1 + +def quickSort(arr, low, high): + """ + Main Quick Sort function that recursively sorts elements before and after partition + """ + if low < high: + # partition the array and get pivot index + pi = partition(arr, low, high) + + # recursively sort the left part + quickSort(arr, low, pi - 1) + + # recursively sort the right part + 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..a1d9d8f0 100644 --- a/Exercise_3.py +++ b/Exercise_3.py @@ -1,21 +1,45 @@ -# Node class + +# Time Complexity : O(n) because we traverse the list once +# Space Complexity : O(1) because we only use two pointers +# Did this code successfully run on Leetcode : NA +# Any problem you faced while coding this : NA + +# Node class for linked list class Node: - - # Function to initialise the node object + # Initialize a node with data and next pointer def __init__(self, data): + self.data = data + self.next = None +# Linked List class class LinkedList: - def __init__(self): - - + self.top = None # head of the list + + # Add a new element to the end of the list def push(self, new_data): + temp = Node(new_data) + if self.top is None: # if list is empty + self.top = temp + else: + curr = self.top + while curr.next: # go to the last node + curr = curr.next + curr.next = temp # attach new node at the end - - # Function to get the middle of - # the linked list + # Function to get the middle of the linked list def printMiddle(self): + slow = self.top # moves one step at a time + fast = self.top # moves two steps at a time + + # traverse the list + while fast is not None and fast.next is not None: + fast = fast.next.next # move fast pointer twice + slow = slow.next # move slow pointer once + # when fast reaches end, slow is at the middle + + print( slow.data) # Driver code list1 = LinkedList() list1.push(5) @@ -23,4 +47,5 @@ def printMiddle(self): list1.push(2) list1.push(3) list1.push(1) + list1.printMiddle() diff --git a/Exercise_4.py b/Exercise_4.py index 9bc25d3d..0942c57e 100644 --- a/Exercise_4.py +++ b/Exercise_4.py @@ -1,12 +1,69 @@ -# Python program for implementation of MergeSort +# This is a simple Merge Sort implementation +# Time Complexity : O(n log n) +# Space Complexity : O(n) due to temp arrays used for merging +# Did this code successfully run on Leetcode : NA +# Any problem you faced while coding this : NA + def mergeSort(arr): - - #write your code here + # left and right define the current part of the array we are sorting + left = 0 + right = len(arr) - 1 + + # Only sort if there is more than one element + if left < right: + mid = (left + right) // 2 # find the middle index + + # Recursively sort the left half and right half + l1 = mergeSort(arr[left:mid]) + l2 = mergeSort(arr[mid + 1:right]) + + # lengths of left and right halves + n1 = mid - left + 1 + n2 = right - mid + + # Create temporary arrays to hold the split parts + L = [0] * n1 + R = [0] * n2 + + # Copy data into temp arrays + for i in range(n1): + L[i] = arr[left + i] + for j in range(n2): + R[j] = arr[mid + 1 + j] + + # Merge the temp arrays back into arr + i = j = 0 + k = left + while i < n1 and j < n2: + if L[i] <= R[j]: + arr[k] = L[i] + i += 1 + else: + arr[k] = R[j] + j += 1 + k += 1 + + # Copy any remaining elements of L[] + while i < n1: + arr[k] = L[i] + i += 1 + k += 1 + + # Copy any remaining elements of R[] + while j < n2: + arr[k] = R[j] + j += 1 + k += 1 + + return arr # return the sorted array + + # Code to print the list def printList(arr): + print(arr) - #write your code here + # driver code to test the above code if __name__ == '__main__': diff --git a/Exercise_5.py b/Exercise_5.py index 1da24ffb..6254efd7 100644 --- a/Exercise_5.py +++ b/Exercise_5.py @@ -1,10 +1,70 @@ # Python program for implementation of Quicksort -# This function is same in both iterative and recursive + +# Time Complexity : O(n log n) +# Space Complexity: O(n) due to the explicit stack used +# Did this code successfully run on Leetcode: NA +# Any problem you faced while coding this: NA + +# Partition function (same as recursive Quick Sort) def partition(arr, l, h): - #write your code here + # i tracks the position for elements smaller than pivot + i = l - 1 + pivot = arr[h] # pick the last element as pivot + + # move all smaller elements to the left of pivot + for j in range(l, h): + if arr[j] < pivot: + i += 1 + arr[i], arr[j] = arr[j], arr[i] # swap + # put pivot in its correct position + arr[i + 1], arr[h] = arr[h], arr[i + 1] + return i + 1 +# Main iterative Quick Sort function def quickSortIterative(arr, l, h): - #write your code here + # create a stack to simulate recursion + size = h - l + 1 + stack = [0] * size + + top = -1 # initialize stack top + + # push initial low and high indices + top += 1 + stack[top] = l + top += 1 + stack[top] = h + + # keep processing while stack is not empty + while top >= 0: + # pop high and low from stack + h = stack[top] + top -= 1 + l = stack[top] + top -= 1 + + # partition the current sub-array + p = partition(arr, l, h) + + # if left part exists, push it to stack + if p - 1 > l: + top += 1 + stack[top] = l + top += 1 + stack[top] = p - 1 + + # if right part exists, push it to stack + if p + 1 < h: + top += 1 + stack[top] = p + 1 + top += 1 + stack[top] = h +arr = [10, 7, 8, 9, 1, 5] +n = len(arr) +quickSortIterative(arr,0,n-1) +print ("Sorted array is:") +for i in range(n): + print ("%d" %arr[i]), + \ No newline at end of file