专栏简介 :刷题笔记
题目来源:leetcode,牛客,剑指offer
创作目标:多维度归纳总结,刷题时遇到的拓展性强,重复高的题目与解题思维.
希望在提升自己的同时,帮助他人,,与大家一起共同进步,互相成长.
学历代表过去,能力代表现在,学习能力代表未来!
最近遇到一道基于二分查找的题觉得挺有意思,虽然不算难但一开始小编还是花了不少时间理解题目,且其中也有许多要注意的细节。接下来小编就带大家一步步来透彻的理解吧。
我们可以把这道题理解成将一个非递减数组拆成前后两个数组并求其最小值。如[12345]它的拆法为1.[23451] 前数组为[2345],后数组为[1]。2.[45123] 前数组为[45],后数组为[123]。。。。。由此我们可以发现最小值为数组的旋转点,同样也是两个数组的中间值。
接下来就是理解的重点!!!
例如:
1.[23451] mid为4,left为2,right为1。此时【arr[mid]>arr[right]】说明最小值一定在后数组。所以 left = mid+1;(这里是一个坑最后解释)
2. [45123] mid为1,left为4,rigth为3。此时【arr[mid]<arr[rigth]】说明最小值为mid或在mid之前,因为mid之后的数组要么递增要么都相等但一定大于mid。所以right = mid;
3. 如果mid==right[12222]则不能判断需要right--不断尝试。
!!!!最后解释坑:如果一个数组为[96] left = 9;rigth = 6;mid = 数组中第一个数也就是9。
arr[mid]>arr[right],最小值在后数组,如果我们按left = mid就永远出不去;所以要写成left=mid+1。这
时有同学就有疑问了为什么当arr[mid]<arr[right]时不能写成right = mid-1?
例如 :数组[69] left = 6;rigth = 9;mid = 数组中第一个数也就是6。arr[mid]<arr[right],最小值为mid或在mid之前。right = mid-1;就会报错。因为发生了越界访问。
int minNumberInRotateArray(int* arr, int size) {
//arr为数组,size为数组大小
int left = 0;
int right = size - 1;
while (left < right) {
int mid = left + (right - left) / 2;
if (arr[mid] < arr[right]) {
right = mid ;
}
else if (arr[mid]>arr[right]) {
left = mid + 1;//这里最后解释
}
else if (arr[mid] == arr[right]) {
right--;//如[011111]需要一个个尝试
}
}
return arr[left];
}