Skip to content

Instantly share code, notes, and snippets.

@Per48edjes
Last active November 30, 2022 19:24
Show Gist options
  • Save Per48edjes/11c74e88f94d714bc520215c12953adc to your computer and use it in GitHub Desktop.
Save Per48edjes/11c74e88f94d714bc520215c12953adc to your computer and use it in GitHub Desktop.
Count number of times sorted array has been rotated
def num_rotations(nums: list) -> int:
"""
Returns the number of times a sorted array has been rotated to the right
with the numbers wrapping to the beginning when they are rotated at the end
of the list
>>> nums = [3, 4, 5, 1, 2]
>>> num_rotations(nums)
3
>>> nums2 = [1, 2, 3, 4, 5]
>>> num_rotations(nums2)
0
>>> nums2 = [4, 5, 1, 2, 3]
>>> num_rotations(nums2)
2
>>> nums3 = [34, 200, 1010, 50982, -1]
>>> num_rotations(nums3)
4
>>> nums4 = [20, 30, -100, -2]
>>> num_rotations(nums4)
2
>>> nums5 = [18]
>>> num_rotations(nums5)
0
"""
min_idx = 0
# Binary search for minimum: O(log n) time complexity
def min_finder(nums: list, lower_i: int, upper_i: int) -> int:
nonlocal min_idx
if lower_i > upper_i:
return
mid = lower_i + (upper_i - lower_i) // 2
if nums[lower_i] <= nums[mid]:
min_idx = lower_i if nums[lower_i] < nums[min_idx] else min_idx
min_finder(nums, mid + 1, upper_i)
else:
min_idx = mid if nums[mid] < nums[min_idx] else min_idx
min_finder(nums, lower_i, mid - 1)
min_finder(nums, 0, len(nums) - 1)
return min_idx
@Per48edjes
Copy link
Author

Per48edjes commented Nov 30, 2022

Ah, I actually think min_finder (in its current form) is $O(n)$ according to the Master Method because $2$ recursive calls are made whereas binary search only ever makes $1$ recursive call!

EDIT: Fixed recursive implementation to be properly $O(\log n)$.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment