在某些情况下,不能找到一个合适的条件来划分区间,也就是说不能将整个区间划分为xxoo型。但是在求解的过程中可以不断的去掉一部分区间。
二分法的本质就是每次去掉一部分区间,所以这类问题可以用二分法的思路和模板来解决。而想到用二分需要从时间复杂度上考虑。比如一维的数组,如果brute force 需要O(n),本身又是sorted,那么就可以考虑用二分,在某些条件的判断下,只保留有解的那一部分。
例 lintcode 62. Search in Rotated Sorted Array https://www.lintcode.com/problem/search-in-rotated-sorted-array/
在二分的while循环中,每一次array[mid]都首先看是在更大的那一部分还是更小的那一部分。然后再看target是在有序的那一段,还是剩下的无序的部分。
public class Solution {
public int search(int[] A, int target) {
if(A == null || A.length == 0) return -1;
int left = 0, right = A.length - 1;
while(left + 1 < right){
int mid = (left + right) >>> 1;
if(A[mid] == target) return mid;
if(A[mid] > A[left]){
if(target >= A[left] && target <= A[mid])
right = mid;
else left = mid;
}else{
if(target >= A[mid] && target <= A[right])
left = mid;
else right = mid;
}
}
if(A[left] == target)return left;
if(A[right] == target) return right;
return -1;
}
}
例 lintcode 75. Find Peak Element https://www.lintcode.com/problem/find-peak-element/description
同样的, 也可以找到一个判断条件每次都去掉一部分区间而保留有解的区间。当处在上升段的时候 left = mid,区间右缩,下降段的时候 right = mid,区间左缩,最终一定在非头尾的位置找到顶峰。
public class Solution {
/**
* @param A: An integers array.
* @return: return any of peek positions.
*/
public int findPeak(int[] A) {
int left = 0, right = A.length - 1;
int mid = 0;
while(left + 1 < right){
mid = (left + right) >>> 1;
if(A[mid] > A[mid + 1] && A[mid] > A[mid - 1]) return mid;
else if(A[mid] > A[mid + 1])
right = mid;
else
left = mid;
}
return -1;
}
}
来源:https://www.cnblogs.com/2333wzl/p/12244985.html