From 740e3e3ee667d9c744c91b1f493f40d339b1f63d Mon Sep 17 00:00:00 2001 From: Akash G Krishnan Date: Thu, 1 Oct 2020 10:51:14 +0530 Subject: [PATCH 1/6] Update mergesort.py 1) Updating the merge sort in python as the previous implementation was modifying the input array 2) divided the division part and conquer part of the merge sort algorithm as 2 functions namely mergeSort and merge. 3) function mergeSort divides the function into halves i.e the purpose of the function will be to divide the array 4) function merge will merge 2 halves into a sorted array 5)Added random test cases using shuffle as suggested by @dhruvmanila 6 The time and space complexity of the previous and my version remains the same. i.e (n log(n) time and n log(n) space 7) changed variables as per the python case as required and suggested by @dhruvmanila 8) Updated function names as suggested by @dhurvmanila --- divide_and_conquer/mergesort.py | 94 ++++++++++++++++++--------------- 1 file changed, 52 insertions(+), 42 deletions(-) diff --git a/divide_and_conquer/mergesort.py b/divide_and_conquer/mergesort.py index f31a57251ce6..4c9fdf7c5e00 100644 --- a/divide_and_conquer/mergesort.py +++ b/divide_and_conquer/mergesort.py @@ -1,48 +1,58 @@ -def merge(arr, left, mid, right): - # overall array will divided into 2 array - # left_arr contains the left portion of array from left to mid - # right_arr contains the right portion of array from mid + 1 to right - left_arr = arr[left : mid + 1] - right_arr = arr[mid + 1 : right + 1] - k = left - i = 0 - j = 0 - while i < len(left_arr) and j < len(right_arr): - # change sign for Descending order - if left_arr[i] < right_arr[j]: - arr[k] = left_arr[i] - i += 1 +def merge(left_half, right_half): + sorted_array = [None] * (len(right_half) + len(left_half)) + + pointer1 = 0 # pointer to current index for left Half + pointer2 = 0 # pointer to current index for the right Half + index = 0 # pointer to current index for the sorted array Half + + while pointer1 < len(left_half) and pointer2 < len(right_half): + if left_half[pointer1] < right_half[pointer2]: + sorted_array[index] = left_half[pointer1] + pointer1 += 1 + index += 1 else: - arr[k] = right_arr[j] - j += 1 - k += 1 - while i < len(left_arr): - arr[k] = left_arr[i] - i += 1 - k += 1 - while j < len(right_arr): - arr[k] = right_arr[j] - j += 1 - k += 1 - return arr - - -def mergesort(arr, left, right): + sorted_array[index] = right_half[pointer2] + pointer2 += 1 + index += 1 + while pointer1 < len(left_half): + sorted_array[index] = left_half[pointer1] + pointer1 += 1 + index += 1 + + while pointer2 < len(right_half): + sorted_array[index] = right_half[pointer2] + pointer2 += 1 + index += 1 + + return sorted_array + + +def merge_sort(array): """ - >>> mergesort([3, 2, 1], 0, 2) - [1, 2, 3] - >>> mergesort([3, 2, 1, 0, 1, 2, 3, 5, 4], 0, 8) - [0, 1, 1, 2, 2, 3, 3, 4, 5] + >>> from random import shuffle + >>> array = [-2, 3, -10, 11, 99, 100000, 100, -200] + >>> shuffle(array) + >>> merge_sort(array) + [-200, -10, -2, 3, 11, 99, 100, 100000] + >>> shuffle(array) + >>> merge_sort(array) + [-200, -10, -2, 3, 11, 99, 100, 100000] + >>> shuffle(array) + >>> merge_sort(array) + [-200, -10, -2, 3, 11, 99, 100, 100000] """ - if left < right: - mid = (left + right) // 2 - # print("ms1",a,b,m) - mergesort(arr, left, mid) - # print("ms2",a,m+1,e) - mergesort(arr, mid + 1, right) - # print("m",a,b,m,e) - merge(arr, left, mid, right) - return arr + if len(array) == 1: + return array + + middle = len(array) // 2 + + # Split the array into halves till the array length becomes equal to One + # merge the arrays of single length returned by mergeSort function and + # pass them into the merge arrays function which merges the array + left_half = array[:middle] + right_half = array[middle:] + + return merge(merge_sort(left_half), merge_sort(right_half)) if __name__ == "__main__": From f7a2b5c64544d997df486291e4f88c6d6aa96910 Mon Sep 17 00:00:00 2001 From: Akash G Krishnan Date: Thu, 1 Oct 2020 11:32:07 +0530 Subject: [PATCH 2/6] Update mergesort.py Added in few more test cases added type hints for the functions and parameters as suggested by @dhruvmanila formatted the code using Auto Pep8 --- divide_and_conquer/mergesort.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/divide_and_conquer/mergesort.py b/divide_and_conquer/mergesort.py index 4c9fdf7c5e00..726bc86754bc 100644 --- a/divide_and_conquer/mergesort.py +++ b/divide_and_conquer/mergesort.py @@ -1,4 +1,7 @@ -def merge(left_half, right_half): +from typing import List + + +def merge(left_half: List, right_half: List) -> List: sorted_array = [None] * (len(right_half) + len(left_half)) pointer1 = 0 # pointer to current index for left Half @@ -27,7 +30,7 @@ def merge(left_half, right_half): return sorted_array -def merge_sort(array): +def merge_sort(array: List) -> List: """ >>> from random import shuffle >>> array = [-2, 3, -10, 11, 99, 100000, 100, -200] @@ -40,8 +43,15 @@ def merge_sort(array): >>> shuffle(array) >>> merge_sort(array) [-200, -10, -2, 3, 11, 99, 100, 100000] + >>> array = [-200] + >>> merge_sort(array) + [-200] + >>> array = [-2, 3, -10, 11, 99, 100000, 100, -200] + >>> shuffle(array) + >>> sorted(array) == merge_sort(array) + True """ - if len(array) == 1: + if len(array) <= 1: return array middle = len(array) // 2 From 36ba9d802060b5d8413ee177619a00fcfcbf89e3 Mon Sep 17 00:00:00 2001 From: Akash G Krishnan Date: Tue, 13 Oct 2020 19:24:24 +0530 Subject: [PATCH 3/6] Update mergesort.py update and added new testcases --- divide_and_conquer/mergesort.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/divide_and_conquer/mergesort.py b/divide_and_conquer/mergesort.py index 726bc86754bc..24b14af5a896 100644 --- a/divide_and_conquer/mergesort.py +++ b/divide_and_conquer/mergesort.py @@ -50,11 +50,21 @@ def merge_sort(array: List) -> List: >>> shuffle(array) >>> sorted(array) == merge_sort(array) True + >>> array = [-2] + >>> merge_sort(array) + [-2] + >>> array = [] + >>> merge_sort(array) + [] + >>> array = [10000000, 1, -1111111111, 101111111112, 9000002] + >>> sorted(array) == merge_sort(array) + True """ if len(array) <= 1: return array - - middle = len(array) // 2 + # the actual formula to calculate the middle element = left + (right - left) // 2 + # this avoids integer overflow in case of large N + middle = 0 + (len(array) - 0) // 2 # Split the array into halves till the array length becomes equal to One # merge the arrays of single length returned by mergeSort function and From 6997cd6668986757490bb8abfb3e80693dbab1e2 Mon Sep 17 00:00:00 2001 From: Akash G Krishnan Date: Thu, 15 Oct 2020 11:16:51 +0530 Subject: [PATCH 4/6] Update mergesort.py Added in doc test in merge function --- divide_and_conquer/mergesort.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/divide_and_conquer/mergesort.py b/divide_and_conquer/mergesort.py index 24b14af5a896..9d256fc15951 100644 --- a/divide_and_conquer/mergesort.py +++ b/divide_and_conquer/mergesort.py @@ -2,6 +2,28 @@ def merge(left_half: List, right_half: List) -> List: + ''' + >>> left_half = [-2] + >>> right_half = [-1] + >>> merge(left_half, right_half) + [-2, -1] + >>> left_half = [1,2,3] + >>> right_half = [4,5,6] + >>> merge(left_half, right_half) + [1, 2, 3, 4, 5, 6] + >>> left_half = [-2] + >>> right_half = [-1] + >>> merge(left_half, right_half) + [-2, -1] + >>> left_half = [12, 15] + >>> right_half = [13, 14] + >>> merge(left_half, right_half) + [12, 13, 14, 15] + >>> left_half = [] + >>> right_half = [] + >>> merge(left_half, right_half) + [] + ''' sorted_array = [None] * (len(right_half) + len(left_half)) pointer1 = 0 # pointer to current index for left Half From b549433bd8958d1dbf3fb14825fc703dbafebfbe Mon Sep 17 00:00:00 2001 From: Akash G Krishnan Date: Thu, 15 Oct 2020 11:23:44 +0530 Subject: [PATCH 5/6] Update mergesort.py fixing pre-commit fails --- divide_and_conquer/mergesort.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/divide_and_conquer/mergesort.py b/divide_and_conquer/mergesort.py index 9d256fc15951..a72de3f048fe 100644 --- a/divide_and_conquer/mergesort.py +++ b/divide_and_conquer/mergesort.py @@ -2,7 +2,7 @@ def merge(left_half: List, right_half: List) -> List: - ''' + """ >>> left_half = [-2] >>> right_half = [-1] >>> merge(left_half, right_half) @@ -23,7 +23,7 @@ def merge(left_half: List, right_half: List) -> List: >>> right_half = [] >>> merge(left_half, right_half) [] - ''' + """ sorted_array = [None] * (len(right_half) + len(left_half)) pointer1 = 0 # pointer to current index for left Half From 8190951ae943c530460e16e8ae9e1d78902e6dcd Mon Sep 17 00:00:00 2001 From: Dhruv Date: Thu, 15 Oct 2020 13:48:12 +0530 Subject: [PATCH 6/6] Update mergesort.py --- divide_and_conquer/mergesort.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/divide_and_conquer/mergesort.py b/divide_and_conquer/mergesort.py index a72de3f048fe..46a46941cab3 100644 --- a/divide_and_conquer/mergesort.py +++ b/divide_and_conquer/mergesort.py @@ -2,23 +2,28 @@ def merge(left_half: List, right_half: List) -> List: - """ + """Helper function for mergesort. + >>> left_half = [-2] >>> right_half = [-1] >>> merge(left_half, right_half) [-2, -1] + >>> left_half = [1,2,3] >>> right_half = [4,5,6] >>> merge(left_half, right_half) [1, 2, 3, 4, 5, 6] + >>> left_half = [-2] >>> right_half = [-1] >>> merge(left_half, right_half) [-2, -1] + >>> left_half = [12, 15] >>> right_half = [13, 14] >>> merge(left_half, right_half) [12, 13, 14, 15] + >>> left_half = [] >>> right_half = [] >>> merge(left_half, right_half) @@ -53,31 +58,35 @@ def merge(left_half: List, right_half: List) -> List: def merge_sort(array: List) -> List: - """ + """Returns a list of sorted array elements using merge sort. + >>> from random import shuffle >>> array = [-2, 3, -10, 11, 99, 100000, 100, -200] >>> shuffle(array) >>> merge_sort(array) [-200, -10, -2, 3, 11, 99, 100, 100000] + >>> shuffle(array) >>> merge_sort(array) [-200, -10, -2, 3, 11, 99, 100, 100000] - >>> shuffle(array) - >>> merge_sort(array) - [-200, -10, -2, 3, 11, 99, 100, 100000] + >>> array = [-200] >>> merge_sort(array) [-200] + >>> array = [-2, 3, -10, 11, 99, 100000, 100, -200] >>> shuffle(array) >>> sorted(array) == merge_sort(array) True + >>> array = [-2] >>> merge_sort(array) [-2] + >>> array = [] >>> merge_sort(array) [] + >>> array = [10000000, 1, -1111111111, 101111111112, 9000002] >>> sorted(array) == merge_sort(array) True