求旋转数组的最小元素

(把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个排好序的数组的一个旋转,输出旋转数组的最小元素。例如数组{3, 4, 5, 1, 2}为{1, 2, 3, 4, 5}的一个旋转,该数组的最小值为1)

除了正常情况,还要注意考虑三种特殊情况:

(1). 数组是没有发生过旋转的 {1,2,3,4,5,6}

(2). 全相等的数组 {1,1,1,1,1,1}

(3). 大部分都相等的数组 {1,0,1,1,1,1}

 二分查找的思路,最开始  如果数组没有旋转过,直接返回第一个元素,就是最小的元素; 如果旋转过,再按后续

首先获得 mid。 此时 ,若

  (1)  如果 ar[mid] > ar[left], 代表最小值肯定在后半区  left = mid + 1

  (2)  如果 ar[mid] < ar[left], 代表最小值肯定是在前半区到mid之间的(mid也有可能是最小值),  right = mid

  (3)  如果 ar[mid] == ar[left], 这种情况不好说了,需要进一步分析:

                 (1)若 ar[mid] == ar[right] , 最麻烦的情况,前中后都相等,只好排除首尾,继续找   left++   right--

                 (2)若 ar[mid] < ar[right], 代表最小值肯定在前半区, right = mid

                 (3)若 ar[mid] > ar[right], 代表最小值肯定在后半区, left = mid + 1

int xuanzhaunjuzhen(int ar[],int left,int right)
{
    int mid;
    while (left < right)
    {
        if (ar[left] < ar[right])         //代表没有旋转过
            return ar[left];
        mid = (left + right)/2;
        if (ar[mid] > ar[left])         // 最小值在后半区
            left = mid + 1;
        else if (ar[mid] < ar[left])    // 最小值在前半区到mid之间
            right = mid;                 //mid也可能是最小值
        else                        //ar[mid] == ar[left] 
        {
            if (ar[mid] == ar[right])
            {
                ++left;
                --right;
            }
            else if (ar[mid] < ar[right])     //在前半区
                right = mid - 1;
            else           //ar[mid] > ar[right]    在后半区
                left = mid + 1;
        }
    }
    return ar[left];
}
原文地址:https://www.cnblogs.com/itachi7/p/2706602.html