diff --git a/Exercise_1.py b/Exercise_1.py index 3e6adcf4..9aaa043f 100644 --- a/Exercise_1.py +++ b/Exercise_1.py @@ -1,22 +1,48 @@ # Python code to implement iterative Binary # Search. + +# // Time Complexity : O(logn) +# // Space Complexity : O(1) saving the index in index variable +# // Did this code successfully run on Leetcode : Yes +# // Any problem you faced while coding this : No # It returns location of x in given array arr # if present, else returns -1 def binarySearch(arr, l, r, x): #write your code here - + # assuming the given array is a sorted array + # binary search is usualy performed on sorted arrays, and since we know its sorted and given a value it will be in range left < value < right so once we found the + # mid of the array and its value is greater than the value we are looking for, no need to look for the right half since all those values + # will be greater than the x so update the right as mid -1 (we already checked mid why to check again and also if we equate left and right to mid it will go on infinte loop) + # same with left variable once the value of mid is less than x then left half all the values will be less than x, no need to iterate the left half + # updte the left = mid +1 + # iterate the loop to find the index if not found return -1 + + + index = -1 # if index found retun the index if ot return -1 so saving the index with -1 + + while ( l <= r): + mid = (l+r)//2 + if arr[mid] == x: + index = mid + return index # once found updating the index + elif arr[mid] > x : + r = mid -1 + else : + l = mid + 1 + + return index # Test array arr = [ 2, 3, 4, 10, 40 ] -x = 10 +x = 12 # 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..c7096262 100644 --- a/Exercise_2.py +++ b/Exercise_2.py @@ -1,16 +1,58 @@ # Python program for implementation of Quicksort Sort +# what's a quick sort : quick sort is an divide and conquer method, so we first set a pivot it can be anything i will chose last element, and then we do partitions +# we split the array into 2 partitions, left partition elements which are less or equal to the pivot and the right where elements are greater than the pivot +# recursively do the same for the left and right arrays ( why?? why is it not enough if we do once, lets go through the following eample) +# in the given example the last element is 5 so we sort it as follows +# 10 > 5 so it will be right side same as 7,8 ,9 also so now the final array will be [1,5,10,7,8,9], is the right array sorted ?? no , that's why recursively do quick sort for left and right arrays +# then when do we stop ? the stop condition is low< high untill then we will do once low=high the array has be sorted + +# // Time Complexity : O(nlogn) best complexity, O(n2) worst complexity +# // Space Complexity : O(logn) though the sorting happens in place, we use recrussion and recurrison is last in first out, underneath uses stack, +# the depth = number of divisions, in best case depth = logn O(logn), worst case depth = n O(n) +# // Did this code successfully run on Leetcode : Yes +# // Any problem you faced while coding this : Need to revise quicksort concept # give you explanation for the approach 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] # we are swaping so basically the value less then the pivot will in moved to the left side of the array + # so at thsi point lets say low is at index 2, then i wil be index 1, and j in ist iteration will be 2, and arr[2] < pivot, so we swap arr[2], arr[1] + # and we move i from 1 to 2 i+=1 is for that, so in next iteration i = 2, j = 3 and if arr[j]< pivot again swap swap until the arr[j] < pivot so + # elemets less than the pivot are in left side of the array. + # we no need to write code to handle elements greater then pivot + # why ? because when we iterativly do , we put the elemenst which are less than pivot in the front, thus pusing the elemenst greater than pivot to the end of the array + # next we have to put our pivot value right after the smaller than pivot elements so in the whole loop until i we have found the elemnst less the pivot + + # once the for loop is done, i is the index of the element found in the array which is less than pivot so the + # pivot postion is next to the ith index so swap it + arr[i+1], arr[high] = arr[high], arr[i+1] # pivot it kept in its correct position + + return i+1 # partition index, so left of this index have values less than pivot and right greater then pivot + + # Function to do Quick sort def quickSort(arr,low,high): #write your code here + if low < high: + pi = partition(arr,low,high) # gives us the parttion index (if pivot is always smallest or largest then the worst complexity is o(n2)) + # so if the pivot is the largest then in fist go only all the elements left are small than pivot but those elemenst migth not be sorted so have to keep sortign again and again same with the pivot being smallest too + # in general case, pivot splits the array into 2 almsot equal parts , each partition takes O(n) to scan through the array, rearrange them takes O(n) + # each recrussion takes O(logn), totol complexity O(nlogn) + quickSort(arr,low,pi-1) # sort the left array of the partition + quickSort(arr,pi+1,high) # sort the right array of the partion + + + # Driver code to test above arr = [10, 7, 8, 9, 1, 5] diff --git a/Exercise_3.py b/Exercise_3.py index a26a69b8..8f0b2b32 100644 --- a/Exercise_3.py +++ b/Exercise_3.py @@ -2,19 +2,57 @@ class Node: # Function to initialise the node object - def __init__(self, data): + def __init__(self, data): + self.data = data + self.next = None class LinkedList: def __init__(self): + self.head = None def push(self, new_data): - + push_node = Node(new_data) + if self.head is None: + self.head = push_node + return + + current = self.head + + while current.next: + current = current.next + + current.next = push_node # keeping in the end # Function to get the middle of # the linked list def printMiddle(self): + # simple logic we want to find middle of linked list + # we can't do like other cases like len(datasturcture)/2 to find the mid, because to find the len of the linked list we need to parse the whole + # linked list and its complexity will be o(n) + # but is there a way to not to parse n times but find the mid + # yes, simple logic so we need to find mid, lets keep a variable to move 1step and one more variable 2 steps + # when the second variable reached the end the first variable will be at mid, 2x = len, x = mid + # simple logic + # edge case we have to handle when the liked list length if even and odd + # so in even case if fast is none then we found the mid, odd case if fast.next is none then we found the mid + + if not self.head: + return None + + slow = self.head + fast = self.head + + while fast and fast.next : + slow = slow.next # moving one step + fast = fast.next.next # moving 2 steps + + return slow.data + # let the linked list be 0-1-2-3-4 odd length, slow =0, fast= 0 next slow =1, fast = 2, slow = 2, fast = 4 ( no more fast.next) so we found the mid + # let the linked list be 0-1-2-3-4-5 even length, same as above, slow = 3, fast = None the while loop stops as fast is noen and we get the mid + + # Driver code list1 = LinkedList() @@ -23,4 +61,4 @@ def printMiddle(self): list1.push(2) list1.push(3) list1.push(1) -list1.printMiddle() +print(list1.printMiddle()) diff --git a/Exercise_4.py b/Exercise_4.py index 9bc25d3d..1030776d 100644 --- a/Exercise_4.py +++ b/Exercise_4.py @@ -1,11 +1,52 @@ # Python program for implementation of MergeSort +# // Time Complexity : +# // Space Complexity : +# // Did this code successfully run on Leetcode : Yes +# // Any problem you faced while coding this : No +# merge sort : first divide array into half parts, and recurively sort the each half and then merge the sorted halves into one sorted array +# since adding the sorted halves into array a new array where the elemsts are sorted the space complexity is O(n) def mergeSort(arr): #write your code here + if len(arr)<2: # split array into equal parts + return arr + + mid = len(arr)//2 + + left_half = arr[:mid] + right_half = arr[mid:] + + mergeSort(left_half) + mergeSort(right_half) + + i = j = k = 0 + + while i< len(left_half) and j < len(right_half): # sort each array and add the sorted elements into arr + if left_half[i] < right_half[j]: + arr[k] = left_half[i] + i+=1 + else: + arr[k] = right_half[j] + j+=1 + k += 1 + + while i< len(left_half): # adding rest of the elements in the array + arr[k] = left_half[i] + i+= 1 + k += 1 + + while j< len(right_half): + arr[k] = right_half[j] + j+= 1 + k+= 1 + + return arr + # Code to print the list def printList(arr): - + for i in range(len(arr)): + print(arr[i]) #write your code here # driver code to test the above code diff --git a/Exercise_5.py b/Exercise_5.py index 1da24ffb..5d0ecbab 100644 --- a/Exercise_5.py +++ b/Exercise_5.py @@ -1,10 +1,41 @@ # Python program for implementation of Quicksort +# // Time Complexity : +# // Space Complexity : +# // Did this code successfully run on Leetcode : Yes +# // Any problem you faced while coding this : No # 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 + # quick sort can be donw in 2 ways recursive or iterative + # iterative approach is + # parition method takes care of putting the pivot in the right place making the array before pivot less than pivot and after the pivot greater than pivot + # same way, lets do the parition until left is less than right + # use stack to keep track of the left and right pivots + stack = [(l,h)] # intially sent the whole array range left to right + + while stack: + l,h = stack.pop() # pops the first index and the last index + if l pivot + stack.append((l,p-1)) # next is to sort the left array so keep sorting the left array, we know the left arra is sorted once the low index is less than the high index + stack.append(p+1,h) # same with right subarray, sort the subarray + # finally when both the arrays are sorted there will be no more elements in the stack and the array is sorted + + + +