Python程序员面试算法宝典---解题总结: 第4章 数组 4.3 如何找出旋转数组的最小元素

# -*- 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()

猜你喜欢

转载自blog.csdn.net/qingyuanluofeng/article/details/92384916