hello,今天我们分享一道题目,是牛客网上的一道题
求旋转数组中的最小值https://www.nowcoder.com/practice/9f3231a991af4f55b95579b44b7a01ba?tpId=13&tqId=23269&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking
那我们先来看一下题目的意思,首先要读懂题目讲的是什么
题目说一个非降序数组,什么是非降序呢,像1 2 3 4 5这种升序 也可以是1 1 2 2 3 4这种,但是大家可不要误解认为他是非序,非序就是随机数这些。
这道题呢有两种解法,一种就是我们从前往后一个一个比较过去,先定义一个min=首项,然后比他小的就赋值给min,这种大家就会,那今天我们就讲一下用二分查找的思路来给大家写
二分查找呢就是一个有序数组中,我们想要找一个数的位置的时候 ,我们取中间的数来进行比较,比如有一个升序数组,我们取出中间数,和我们要取的值进行比较,如果大于中间数,说明这个数在这个中间数的后面,那我们取中间数后面的数一直到最后的数的中间数,在进行比较,经过我们这样找数的方式,可以快速的找到它的位置
那我们就可以用这样的思路来分析这道题
- 中间大于右边 [3, 4, 5, 1, 2],这种情况下,最小数一定在右边;则left = middle + 1
- 中间等于右边 [1, 0, 1, 1, 1], 这个是[0, 1, 1, 1, 1] 旋转过来的,这时候需要缩小范围 right–;,注意不能是
left++,因为是非降序数组,所以要缩小右边范围,把较小值向右推,符合我们的判断规则。- 中间小于右边 [5, 1, 2, 3, 4], 这种情况下,最小数字则在左半边;则right = middle
int minNumberInRotateArray(int* rotateArray, int rotateArrayLen ) {
if (rotateArrayLen == 0) return 0;
int left = 0, right = rotateArrayLen - 1, mid;
if (rotateArray[right] > rotateArray[left]) return rotateArray[0];
while(left < right) {
mid = left + (right - left) / 2;
if (rotateArray[mid] > rotateArray[right]) left=mid+1;
//中间的数大,那么我们就要往mid后面找,说明最小值在mid后面
//而且保证mid不是最小数,因为right有更小的数
else if (rotateArray[mid] == rotateArray[right]) right--;
//如果是这样的旋转数{0,1,1,1,1,1,1}
else right = mid;//中间的数小,那我们就要往右边找,而且这个中间数也可以是最小的数,所以不能写成right=mid-1
}
return rotateArray[left];//因为只有right=left的时候while循环条件不满足,那么才会退出循环,所以这里写right也对
}
今天的分享就到这,我们一起加油