牛客网/剑指offer/3.找旋转后的数组中的最小值
题目:
有一个长度为 n 的非降序数组,比如[1,2,3,4,5],将它进行旋转,即把一个数组最开始的若干个元素搬到数组的末尾,变成一个旋转数组,比如变成了[3,4,5,1,2],或者[4,5,1,2,3]这样的。请问,给定这样一个旋转数组,求数组中的最小值。
数据范围:1 \le n \le 100001≤n≤10000,数组中任意元素的值: 0 \le val \le 100000≤val≤10000
要求:空间复杂度:O(1)O(1) ,时间复杂度:O(logn)O(logn)
python语法:
1.逻辑运算符:
and or not 条件过长可以加括号
2.位运算
x >> 1 等价于 x/2
算法思路:
输出旋转后数组,二分判断:
#1.中值<前一个数,中值为最小值
#2.中值<右边,中值在左边
#3.其他,中值在右边
#二分:初始化right、left,不断更新计算-->mid
此算法问题:如何处理以下特殊输出:
[2 2 2 2 1 2]
[1 2 2 2 2 2]
[5 1 2 5 5 5]
若中值=右边,但最小值可能在前半部分,也可能在后半部分,算法失效。
对以上算法做改进:如果中值与左边和右边都相同,那说明有一边必定是全部相同的数字,结合mid的相邻元素可以排除一边。
实现为:
elif rotateArray[mid] < rotateArray[right] or (rotateArray[mid] == rotateArray[right] and rotateArray[mid] == rotateArray[mid+1]):
right = mid -1
ps: 遇到[2 2 2 2 2 2 2 1 2] 还是不行,最终需要解决的是 如何跳过大量相等的元素。
代码实现:
class Solution:
def minNumberInRotateArray(self, rotateArray):
# write code here
left = 0
right = len(rotateArray) - 1
while left <= right:
mid = (left + right) >> 1
if rotateArray[mid] < rotateArray[mid - 1]:
return rotateArray[mid]
elif rotateArray[mid] < rotateArray[right] or (rotateArray[mid] == rotateArray[right] and rotateArray[mid] == rotateArray[mid+1]):
right = mid -1
else:
left = mid + 1
return 0