题目一:Suppose a sorted array is rotated at some pivot unknown to you beforehand.
(i.e., 0 1 2 4 5 6 7
might become 4 5 6 7 0 1 2
).
Find the minimum element.You may assume no duplicate exists in the array.
思路:
二分查找是分治思想,主要应用于有序顺组相关的查找问题。
典型的应用有:
1、最常规问题:在有序数组中查找某个值。
2、有序数组中查找某个值的所在范围。http://blog.csdn.net/ojshilu/article/details/17125531
3、在循环有序数组中查找某个值。http://blog.csdn.net/ojshilu/article/details/17485787
4、在循环有序数组中查找数组最小值(即循环偏移位置)。http://blog.csdn.net/ojshilu/article/details/40296471
二分查找的主要步骤:
一般都是根据左右边界left和right来控制查找范围,取得中间位置A[mid],依据mid位置的值来选择下一步向什么范围查找。这其中包含了两个细节:
1、A[mid]和谁比较;
2、比较之后如何缩小问题范围;
对于上面说的四种应用,所采用的这两个细节是不同的。
代码:
class Solution { public: int findMin(vector<int> &num) { int left, right, mid; left = 0, right=num.size()-1; mid = (left + right)/2; while(left < right) { mid = (left + right)/2; if(num[mid] > num[left]) //转折点到右侧 left = mid; else if (num[mid] < num[left]) //转折点在左侧 right = mid; else // left+1 == right { mid++; break; } } int min = num[mid]; min = (min<num[0])?min:num[0]; //如果并未循环移动过 return min; } };
(i.e., 0 1 2 4 5 6 7
might become 4 5 6 7 0 1 2
).
Find the minimum element.
The array may contain duplicates.
思路:
重复元素的出现让二分查找变得困难,面对相等关系有时候二分会变得难以抉择。因此,对于可以明确选择分支的情况,就选择进去;对于无法判定分支的情况,两个分支分别递归进去处理。
代码:
class Solution { public: int _find(vector<int> &num, int left, int right) //返回的是下标 { if(left + 1 == right) { //cout<<"left = "<<left<<" right="<<right<<endl; return num[left]<num[right]?left:right; } int mid; while(left + 1 < right) { mid = (left + right)/2; if(num[mid] > num[left]) //转折点到右侧 left = mid; else if (num[mid] < num[left]) //转折点在左侧 right = mid; else //转折点不确定 { int m1 = _find(num, left, mid); int m2 = _find(num, mid, right); return num[m1]<num[m2]?m1:m2; } } //cout<<"left = "<<left<<" right="<<right<<endl; return num[left]<num[right]?left:right; } int findMin(vector<int> &num) { int left, right; left = 0, right = (int)num.size()-1; int min = _find(num ,left, right); if(num[min] > num[0]) min = 0; return num[min]; } };