Working on this challenge on HackerRank and got this code to pass 10 out of 15 test cases. It is failing due to timeout error which is HackerRank's way of telling you that the algorithm is not optimized. How can I optimize this code to run on larger input data?
The goal is to figure out the minimum number of swaps necessary to sort an unsorted array.
Update: Each element in the array is distinct.
def minimum_swaps(arr):
"""Returns the minimum number of swaps to re-oder array in ascending order."""
swaps = 0
for val in range(len(arr) - 1, 0, -1):
# Index of max value
max_pos = 0
for index in range(1, val + 1):
if arr[index] > arr[max_pos]:
max_pos = index
# Skip if value is already in sorted position
if max_pos == val:
continue
arr[val], arr[max_pos] = arr[max_pos], arr[val]
swaps += 1
return swaps
Look at the code. It has 2 nested loops:
val
.val
, i.e.,max_pos
.It takes a lot of time just to find the index. Instead, I will compute the index of each value and store it in a
dict
.(note that because all values in
arr
are distinct, there should be no duplicated keys)And also prepare a sorted version of the array: that way it's easier to find the maximum value instead of having to loop over the array.
Then do the rest similar to the original code: for each index visited, use
sorted_arr
to get the max, useindex_of
to get its current index, if it's out-of-place then swap. Remember to update theindex_of
dict while swapping too.The algorithm takes
O(n)
operations (includingdict
indexing/modifying), plus sorting cost ofn
elements (which is aboutO(n log n)
).Note: If the array
arr
only contains integers in a small range, it may be faster to makeindex_of
an array instead of adict
.The short answer is: implement merge sort. The bubble sort algorithm you are using has a O(n^2) running time, while merge sort has a O(log_2(n)) running time.