在有序旋转数组中找到最小值
升序旋转数组最小值
【题目】
有序数组arr可能经过一次旋转处理,也可能没有,且arr可能存在重复的数。
例如,有序数组[1,2,3,4,5,6,7],可以旋转处理成[4,5,6,7,1,2,3] 等。
给定一个可能旋转过的有序数组arr,返回arr中的最小值。
算法思路
根据题目分析
有序指升序;
旋转处理将升序数组分成前后两部分,进行整体位置交换;
可能旋转,可能不旋转,返回其中最小值
直接遍历获取最小值,时间复杂度为 O ( N ) O(N) O(N)。
现在考虑升序数组和旋转操作的性质,给定的数组arr最多下降一次值(散点构成的两条向上的直线)。
使用二分查找的思想,平均时间复杂度为
O
(
l
o
g
N
)
O(logN)
O(logN),最坏时间复杂度为
O
(
N
)
O(N)
O(N)。
思维扩展
同理可以在升序旋转数组中找到最大值;
也可以先找到最小值的索引,最小值前一位就是最大值。(若最小值索引为0,则最大值索引为-1——len(arr) - 1)。
相应代码
# 有序旋转数组最小值
def rotate_arr_minimum(arr):
if arr is None or len(arr) == 0:
return None
low = 0
high = len(arr) - 1
while low <= high:
# 包含不超过两个值
if high - low <= 1:
minimum = arr[low]
if arr[high] < arr[low]:
minimum = arr[high]
return minimum
# 无旋转
if arr[low] < arr[high]:
return arr[low]
# 二分查找
mid = (low + high) // 2
if arr[low] > arr[mid]:
high = mid
elif arr[mid] > arr[high]:
low = mid
else:
# arr[low] == arr[mid] == arr[high], 最小值在下面五个位置中
cand_indexes = [low + 1, mid - 1, mid, mid + 1, high -1]
minimum = arr[cand_indexes[0]]
for index in cand_indexes:
if arr[index] < minimum:
minimum = arr[index]
return minimum
# 简单测试
if __name__ == '__main__':
arr = [4, 5, 6, 7, 1, 2, 3]
print(rotate_arr_minimum(arr)) # 1
arr = [1, 1, 1, 1, 1, 1, 1]
print(rotate_arr_minimum(arr)) # 1
arr = [1, 0, 1, 1, 1, 1, 1]
print(rotate_arr_minimum(arr)) # 0
arr = [1, 1, 1, 1, 1, 0, 1]
print(rotate_arr_minimum(arr)) # 0
有任何疑问和建议,欢迎在评论区留言和指正!
感谢您所花费的时间与精力!