寻找旋转数组的最小值

所谓旋转数组就是讲数组后面的若干个数放到数组前面。
给定一个递增数组 a[4,5,1,2,3],找出他的最小值

第一种思路:从头到尾遍历一遍:时间复杂度 O(n),并没有用到数组递增的特点

第二种思路:利用数组的递增特点,因为数组是递增的,当我们把后半部分放到前半部分之后,整个数组相当于被划分成了两个递增的子数组,所以可以采用二分查找的方式,思路如下:

有两个指针index1和 index2,其中 index1指向第一个递增数组的第一个元素,index2指向第二个递增数组的最后一个元素,并且 index1指向的元素一定大于或者等于 index2指向的元素(因为 在原来的递增数组中,index1指向的元素一开始是在 index2指向的元素的后面),当 index1和 index2相邻的时候,也就是我们找到了那个元素,而且这个元素一定是 index2指向的,因此循环结束的条件就是 index2-index1=1,
否则就计算出 mid,如果 mid 指向的大于 index1指向的元素,说明,最小的在 mid 的后面,这时候改变 index1的指向,让其指向 mid,如果 mid 指向的小于 index2指向的元素,mid 在第二个递增子数组,那么最小的在 mid 指向的那个元素的前面,所以让 index2指向 mid,正阳一直循环,知道找到退出
代码如下

//寻找旋转数组的最小数字
int findMin(int a[],int n){
    int index1 = 0;//指向第一个递增子数组的第一个位置
    int index2 = n-1;//指向第二个递增子数组的最后一个位置
    while (a[index1]>=a[index2]) {
        if (index2-index1 == 1) {//循环结束条件,index1指向第一个递增子数组末尾,index2指向第二个递增子数组开头,那么最小的一定是 index2指向的
            return a[index2];
        }
        int mid = (index1+index2)/2;//计算出中间 mid
        if (a[mid]>=a[index1]) {//说明中间的数在第一个递增子数组,那么最小值在后面的那个子数组
            index1 = mid;
        }
        else{//否则相反
            index2 = mid;
        }
    }
    return a[index2];
}

对于特殊情况 a[1,1,1,0,1]第一个最后一个和中间的都是1,那就只能用从头到尾遍历的方式了

猜你喜欢

转载自blog.csdn.net/li15809284891/article/details/69950388