剑指offer—旋转数组的最小数字
题目描述:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
该题考查的是如何使用时间复杂度小于O(n)
的方法来找到这个最小值,由于旋转数组的特性,可以发现旋转后的数组被划分成了两个排序数组,前半部分的值都大于后半部分的值,而最小值则可以作为这个部分的一个分界点。因此可以使用二分法 来解决这个问题。使用i
和j
来分别指向旋转数组的头和尾。并分别和他们之间的中间位置mid
的数字进行比较。
如果mid
大于等于i
的值,则说明最小值应当出现在数组的后半部分,这时将i
移到mid
的位置,继续进行判断。
如果mid
小于j
的值,则说明最小值应当在这个中间值的前面,这时将j
移到mid
的位置,继续进行判断。
直到i
与j
位置相邻,这时i
将会指向前半部分的数组的最后一个数字,而j
则指向后半部分数组的第一个数字,该数字刚好为最小的数字。
代码如下:
# -*- coding:utf-8 -*-
class Solution:
def minNumberInRotateArray(self, rotateArray):
if rotateArray != []:
arr_len = len(rotateArray) - 1
i, j = 0, arr_len
mid = 0
while rotateArray[i] >= rotateArray[j]:
if j - i == 1:
mid = j
break
mid = (j+i)/2
#如果i ,j,mid处的数字相同的话,就只能够顺序查找最小值
if rotateArray[mid] == rotateArray[i] and rotateArray[mid] == rotateArray[j]:
mini = rotateArray[i]
for k in range(i,j):
if rotateArray[k] < mini:
mini = rotateArray[k]
return mini
if rotateArray[mid] >= rotateArray[i]:
i = mid
elif rotateArray[mid] <= rotateArray[j]:
j = mid
return rotateArray[mid]
else:
return 0
在书中,还提出了一种特殊情况,也就是如果i
,j
,和mid
处的数字都相同时,这时无法判断中间的数字是属于那一部分的,因此这种情况下只能够使用顺序查看的方式来找到最小值。