剑指offer——旋转数组最小数字问题

今天做到旋转数字最小数字时,看到需要考虑的边界有些麻烦,因而分析总结一下。
旋转数组其实就是一个递增排序数组的旋转,例如{3,4,5,1,2}即为{1,2,3,4,5}的一个旋转数组。
旋转数组有一个特性:包含两个递增子序列,因而可以考虑用二分查找简化。设置三个指针low,high,middle,low指向数组低部分,high指向数组高部分,middle指向high,low中间部分。若middle指向数据>low指向数据,则说明最小值位于middle右侧部分;若middle指向数据小于high指向数据,则说明最小值位于middle左侧部分。以上这些很好理解。
但是有两种特殊情况:
1. 数组为一个有序数组。即把数组前面0个元素放在后面。
2. 数组中有多个重复值。例如{1,0,1,1,1}和{1,1,1,0,1}均为{0,1,1,1,1}的旋转数组。
对于第一种情况,上述解决方法仍然适用。
而对于第二种情况,我们无法通过三个指针的数据判断最小值的位置,这个时候,需要退化成顺序查找,让high- -或者low++。
最终可得到代码:

class Solution {
public:
    int minNumberInRotateArray(vector<int> rotateArray) {
        if (rotateArray.size()<=0) {
            return 0;
        }
        int low=0;
        int high=rotateArray.size()-1;
        int middle;
        while (high>=low) {
            if (high==low) {
                break;
            }
            middle=(high+low)/2;
            if (rotateArray[middle]<rotateArray[high] && high>=low) {
                high=middle;
            }
            else if (rotateArray[middle]==rotateArray[high] && high>=low) {
                high--;
            }
            else if (rotateArray[middle]>rotateArray[low] && high>=low) {
                low=middle;
            }
            else if (rotateArray[middle]==rotateArray[low] && high>=low){
                low++;
            }
        }
        return rotateArray[high];
    }
};

对比一下前几天的一道面试题,一个数组前半部分递减,后半部分递增,求最小值。其实拐角处就是最小值。对于这些基本有序的数组,首先要考虑用二分查找来进行简化,其实上述问题就是个变形的二分查找,但是middle指针并不是于high或low指针指向内容进行比较,而是与middle+1指针进行比较,来判断现在middle在递增序列还是递减序列,然后改变high或low指针即可。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值