剑指offer经典题目二:旋转数组的最小数字

x33g5p2x  于2022-01-13 转载在 其他  
字(1.2k)|赞(0)|评价(0)|浏览(242)

剑指offer经典题目二

题目链接旋转数组的最小数字
题目描述:
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。
例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。

题目要求给一个非递减排序的数组的一个旋转,需要输出旋转数组的最小元素,我们可以直接进行遍历去找最小的那个数,但是这种方法肯定是效率最低的

核心考点:数组理解,二分查找,临界条件

方法一思路:
一个非递减的数组左旋之后,最开始出现递减的地方的那个数字就是最小值,我们可以比较相邻的两个数,如果右边的数小于左边的数,那么该右边的这个数字就是最小值,这种方法本质上和上面的没有区别,效率不高

方法二思路:

定义首位下标,因为是非递减数组旋转,所以旋转最后可以看作成两部分,前半部分整体非递减,后半部分整体非递减,前半部分整体大于后半部分。当a[mid]大于等于a[left]时,说明mid属于原数组前半部分,目标最小值,在mid的右侧,让left = mid;当a[mid]小于a[left],说明mid位置在原数组后半部分,说明目标最小值在mid的左侧,让right = mid。

方法二解题代码:

class Solution
{
public:
	int minNumbeiInRotateArray(vector<int> array)
    {
        if(array == nullptr||array.size() == 0)
        {
            return 0;
        }
        int left = 0;
        int right = array.size()-1;
        int mid = 0;
        while(left<right)
        {
            //当right和left相邻时,右边的值是
            
            if(right - left==1)
            {
                mid = right;
                break;
            }
            //如果这三者相等,没有办法判断左半部分还是右半部分
            if(arrar[left] == array[right] && arrar[left] == array[mid])
            {
                //此时遍历式的去找
                int result = array[left];
                for(int i = left+1;i<right;i++)//i不用等于right,因为right是和left相等的不用比较
                {
                    if(result>arrar[i])
                    {
                        result = array[i];
                    }
                }
                return result;
            }
            mid = (right+left)>>1;
            if(array[mid]>=array[left])
            {
                //当a[mid]大于等于a[left]时,说明mid属于原数组前半部分,目标最小值,在mid的右侧
                left = mid;
            }
            else
            {
                //当a[mid]小于a[left],说明mid位置在原数组后半部分,说明目标最小值在mid的左侧
                right = mid;
            }
        }
        return array[mid];
    }
}

相关文章