| #!/usr/bin/env python | |
| # MEDIAN OF MEDIANS | |
| # Reference: https://brilliant.org/wiki/median-finding-algorithm/ | |
| def median_of_medians(arr): | |
| """ | |
| Median of medians is an algorithm to select an approximate median as a pivot for a partitioning algorithm. | |
| :param arr: | |
| :return: | |
| """ | |
| if arr is None or len(arr) == 0: | |
| return None | |
| return select_pivot(arr, len(arr) // 2) | |
| def select_pivot(arr, k): | |
| """ | |
| Select a pivot corresponding to the kth largest element in the array | |
| :param arr: Array from which we need to find the median. | |
| :param k: cardinality that represents the kth larget element in the array | |
| :return: The value of the pivot | |
| """ | |
| # Divide array into chunks of 5 | |
| #chunks by taking i from 0 to 4, 5 to 9, 10 to 14, etc | |
| chunks = [arr[i : i+5] for i in range(0, len(arr), 5)] | |
| #sort each chunks | |
| sorted_chunks = [sorted(chunk) for chunk in chunks] | |
| #take the median of each chunk | |
| medians = [chunk[len(chunk) // 2] for chunk in sorted_chunks] | |
| #find the median of medians | |
| if len(medians) <= 5: | |
| pivot = sorted(medians)[len(medians) // 2] | |
| else: | |
| pivot = select_pivot(len(medians) // 2) | |
| #partition the array around the pivot | |
| p = partition(arr, pivot) | |
| #is the pivot position at the k position? | |
| if k == p: | |
| #select that pivot | |
| return pivot | |
| if k < p: | |
| #select a new pivot by looking on the left side of the partioning | |
| return select_pivot(arr[0:p], k) | |
| else: | |
| #select a new pivot by looking on the right side of the partioning | |
| return select_pivot(arr[p+1:len(arr)], k - p - 1) | |
| def partition(arr, pivot): | |
| """ | |
| Partition the array around the given pivot | |
| :param arr: array to be partitioned | |
| :param pivot: pivot used for the partitioning | |
| :return: final position of the pivot used as a partioning point | |
| """ | |
| left = 0 | |
| right = len(arr) - 1 | |
| i = 0 | |
| while i <= right: | |
| if arr[i] == pivot: | |
| i += 1 | |
| elif arr[i] < pivot: | |
| arr[left], arr[i] = arr[i], arr[left] | |
| left += 1 | |
| i += 1 | |
| else: | |
| arr[right], arr[i] = arr[i], arr[right] | |
| right -= 1 | |
| return left | |
| arr = [1, 2, 3, 4, 5, 1000, 8, 9, 99] | |
| pivot = median_of_medians(arr) | |
| print (pivot) |
plz check line no-43 of code...i think it should be----( pivot = select_pivot(medians,len(medians) // 2) ),otherwise it will show error for larger number of elements in list.