旋转数组的最小元素

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。

例如有如下数组


旋转之后如下

此时需要找出当前旋转数组的最小值,由于数组是递增的,所以旋转之后前面的数组元素会大于后面数组的元素,也就是数组{4, 5}大于{1,2,3}。因此采用二分查找的方法找出最小元素。

标记数组的开头left与结尾right。

(1)如果数组没有进行旋转,则rotateArray[left]为最小元素。

(2)如果发生了旋转,取当前数组的中间元素的下标mid。

a. 假设中间的位置如下图所示


rotateArray[mid]之后所有的值都比rotateArray[mid]大,而前面可能有大可能有小的值,所以将right移动到mid的位置。此时的条件为rotateArray[mid] < rotateArray[left]

b.假设中间位置如下

rotateArray[mid]前面所有的值都比rotateArray[mid]小,但是由于是递增的数组且发生了旋转,所以旋转数组的最小元素一定在mid之后,所以将left移动到mid的位置。此时条件为rotateArray[mid] > rotateArray[left]

c. 如果mid,left,right元素都相等。


此时无法确定最小值在哪个范围内,需要进行查找。

class Solution {
public:
    int minNumberInRotateArray(vector<int> rotateArray);
    int MinValue(vector<int> &rotateArray, int left, int right);
};

int Solution::minNumberInRotateArray(vector<int> rotateArray) {
    
    int value;
    
    if (!rotateArray.size())
        return 0;
    
    int left = 0;
    int right = rotateArray.size() - 1;
    int mid = 0;
    
    while (rotateArray[left] >= rotateArray[right]) {  /* 发生了旋转 */
        
        if (right - left == 1) {
            mid = right;
            break;
        }
      
        mid = left + (right -left) / 2;
        if((rotateArray[left] == rotateArray[mid]) && (rotateArray[left] == rotateArray[right]))  /* mid,left,right元素都相等 */
            return MinValue(rotateArray, left, right);
        
        if (rotateArray[mid] >= rotateArray[left]) /* 最小元素在mid和right之间 */
            left = mid;
        else                                       /* 最小元素在left和mid之间 */
            right = mid; 
    }
    
    return rotateArray[mid];
}

int Solution::MinValue(vector<int> &rotateArray, int left, int right) {
    
    int minvalue = rotateArray[left];
    for (int i = left + 1; i < right + 1; i++) {
        if (minvalue > rotateArray[i])
            minvalue = rotateArray[i];
    }
    return minvalue;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值