【修改版二分查找】旋转数组的最小数字

大致思路:

首先要把题多读几遍,理解题意!

题意:给你一个旋转后的数组,让你找最小值。

发现数字规律:由于是非递减序列,可以先认为就是递增序列,再去考虑相等的情况。以{3,4,5,1,2}这个旋转数组为例,可以知道其实分为两区,左区是更大的。而我们要找的最小的元素,就是左右区的临界元素,这里是1.

对于这种“顺序查找”可以解决的题目,为了优化,最好采用“二分查找”——用left和right两个指针,看mid元素。

而二分查找的nuance就在于:

如何判断“找到”。传统:看Mid元素是否是所查找的值。本题:看left和right是否到了临界区,满足left==right-1,则取array[right]

mid指针如何变化。传统:将mid元素与所查找的值比大小。本题:将mid元素与旋转数组的第一个元素(这里是3)作比较,如果大于说明mid在左区,令left=mid;如果小于说明mid在右区,令right=mid。

 

最后,再考虑相等的特殊情况

我们看一组例子:{1,0,1,1,1} 和 {1,1, 1,0,1} 都可以看成是递增排序数组{0,1,1,1,1}的旋转。

这种情况下我们无法继续用上一道题目的解法,去解决这道题目。因为在这两个数组中,第一个数字,最后一个数字,中间数字都是1。因此,这种特殊情况就直接顺序遍历求最小值来解决。

 

AC代码:

#include<bits/stdc++.h>
#include<iostream>
using namespace std;

class Solution {
public:
    int minNumberInRotateArray(vector<int> rotateArray) {
        if(rotateArray.size()==0)
            return 0;
        int left=0; //指向左区
        int right=rotateArray.size()-1; //指向右区
        int mid;
        //二分查找最小的元素
        while(rotateArray[left]>=rotateArray[right])
        {
        	mid = (left+right)/2;
        	
            //此处找到的条件不是来判断mid元素的值,而是看left和right的关系
            if(left==right-1)
            {
            	mid = right;
            	break;
		    }
        
            //处理特殊情况:相等。只能遍历找最小值
            if(rotateArray[left]==rotateArray[right]&&rotateArray[left]==rotateArray[mid])
            {
                return findMin(rotateArray,left,right);
            }
            //对于一般情况,Left位于左区,right位于右区,需要找到左右区的临界元素,则为最小值
            //二分查找的思想,去判断Mid元素
            if(rotateArray[mid]>=rotateArray[left]) //mid位于左区
                left = mid;
            else //mid位于右区
                right = mid;
        }
        return rotateArray[mid];
    }
    
public:
    int findMin(vector<int>rotateArray,int left,int right)
    {
        int minn=1e9;
        for(int i=left;i<=right;i++)
        {
            minn = min(minn,rotateArray[i]);
        }
        return minn;
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值