美文网首页
剑指OFFER面试题8:旋转数组的最小数字

剑指OFFER面试题8:旋转数组的最小数字

作者: ericlll | 来源:发表于2016-05-19 16:04 被阅读41次

旋转数组的最小数字


前提摘要

关键找出规律:当start指针和end指针分别指向两个相邻元素时,end指针指向的元素即为数组中最小数字,论述见书本。所以二分的目的最后还是缩小搜索范围至两个元素

问题分解

我把可能出现的情况分成四种。

  1. 数组没有经过旋转,此时start指针刚好指向最小数字
  2. 数组发生了旋转,旋转后end指针和start指针指向的刚好是相邻的两个递增元素,start指针指向元素必定大于等于end指针指向元素。
    将数组二分后,根据逻辑判断出最小数字要么在前半段(刚好中间的话先看作前半段),要么在后半段。
    1)如果在前半段,那么start指针指向的元素必定大于middle指针指向的元素,因为a[start]>a[end]a[end]>a[middle](递增序列),使end指向middle的元素从而在前半段继续查找
    2)如果在后半段,同理,end指针指向的元素必定小于middle指针指向的元素,因为a[end]<a[start]a[start]<a[middle],使start指向middle的元素从而在后半段查找
    3)最后考虑极端的情况a[start]==a[middle]==a[end],无法确定前半段还是后半段。我们要做的是打破这种“平衡”情况,可以修改start或者end,同时引起middle的变化,使其回到上面两种情况。注意修改start或者end之后要求数组保持处于旋转状态。假如修改了start那么有可能使数组处于完全递增没有经过旋转状态,只能选择修改end使其向前移动一位
int findleastinspinSorted(int a[],int start,int end){
    if (a==NULL || start>end){
        cout<<"check your parameter"<<endl;
        exit(1);
    }
    if (a[start]<a[end] || start==end){
        return a[start];
    }
    int middle =0;
    while(start!=end-1){
        middle = (start + end)/2;
        if(a[middle]<a[start]){
            end = middle;
        }else if (a[middle]>a[end]){
            start = middle;
        }else{
            end--;      
        }
    }
    return a[end];
}

相关文章

网友评论

      本文标题:剑指OFFER面试题8:旋转数组的最小数字

      本文链接:https://www.haomeiwen.com/subject/nsjgrttx.html