# -*- coding: utf-8 -*-
'''
Python程序员面试算法宝典---解题总结: 第4章 数组 4.3 如何找出旋转数组的最小元素
题目:
把一个有序数组最开始的若干个元素搬到数组的末尾,称之为数组的旋转。
输入一个排好序的数组的一个旋转,输出旋转数组的最小元素。例如:
数组[3,4,5,1,2]为数组[1,2,3,4,5]的一个旋转,该数组的最小值为1。
分析:
可以这样做。首先明白最重要的一点是,一旦数组发生旋转,
那么旋转前一半的元素要大于旋转后的元素。
例如[3,4,5]大于[1,2]
可以每次将数组分半处理对于array[begin]~array[middle]
如果array[middle] > array[begin],说明最小元素一定不在这里,
因为array[begin]~array[middle]是有序的,否则,肯定
在array[begin]~array[middle]中,此时对array[begin]~array[middle]
继续分为两半,递归处理;
同理对于 array[middle+1]~array[end]也做上述处理。
一旦数组只剩两个元素,并且还满足数组第一个元素大于数组第二个元素
则数组第二个元素必然是最小值;
对应例子为: [3,4,5,6,1,2]
还有一种特殊情况:
如果array[begin]~array[middle]有序,
array[middle+1]~array[end]有序,则最小值必定为array[middle+1]。
对应例子为: [3,4,5,6,0,1,2]
我找到最小元素的条件就是如果不断递归遍历
关键:
1 书上解法
mid = (low + high)/2
若前大于后,则后必定是最小值,即满足:
若arr[mid-1] > arr[mid],则arr[mid]是最小
若arr[mid] > arr[mid+1],则arr[mide+1]是最小
若前半部分数组中,第一个元素大于最后一个元素,则在左半区域,即
arr[low] > arr[mid],则在左半部分
若后半部分数组中,第一个元素大于最后一个元素,则在右半区域,即
arr[mid] > arr[high],则在左半部分;
若arr[low] == arr[mid]并且arr[mid] == arr[high],则直接寻找最小值
2 我没想到
如果前后两个数组都是有序的,则可能存在
[1,0,1,1,1,1]这种情况,这种情况需要直接遍历所有。
另外可以通过直接比较arr[mide-1],arr[mid],arr[mid+1]等
去除只有两个元素比较的限制
参考:
Python程序员面试算法宝典
'''
def findMinInRotaedArray_Wrong(data, begin, end):
if not data:
return
if begin > end:
return
if begin == end:
return data[begin]
if begin + 1 == end:
if data[begin] > data[end]:
return data[end]
middle = (end - begin) / 2 + begin
# 判断如果在左半区域,就对左半区域递归处理
if data[middle] < data[begin]:
result = findMinInRotaedArray_Wrong(data, begin, middle)
elif data[end] < data[middle + 1]:
result = findMinInRotaedArray_Wrong(data, middle + 1, end)
else:
result = data[middle + 1]
return result
def findMinInRotaedArray(array, begin, end):
if not array:
return
if begin > end:
return
middle = (begin + end) / 2
if middle >= 1 and array[middle - 1] > array[middle]:
return array[middle]
if middle <= len(array) - 2 and array[middle] > array[middle + 1]:
return array[middle + 1]
if array[begin] > array[middle]:
result = findMinInRotaedArray(array, begin, middle)
elif array[middle] > array[end]:
result = findMinInRotaedArray(array, middle, end)
elif array[begin] == array[middle] and array[middle] == array[end]:
result = min(array)
else:
result = None
return result
def process():
data = [1, 0, 1, 1, 1, 1]
result = findMinInRotaedArray(data, 0, len(data) - 1)
print result
assert result == 0
data = [1, 1, 1, 1, 1, 1]
result = findMinInRotaedArray(data, 0, len(data) - 1)
print result
assert result == 1
data = [3, 3, 4, 5, 6, 0, 1, 2]
result = findMinInRotaedArray(data, 0, len(data) - 1)
print result
assert result == 0
data = [3, 4, 5, 6, 1, 2]
result = findMinInRotaedArray(data, 0, len(data) - 1)
print result
assert result == 1
data = [3, 4, 5, 6, 0, 1, 2]
result = findMinInRotaedArray(data, 0, len(data) - 1)
print result
assert result == 0
if __name__ == "__main__":
process()