在某些情况下,不能找到一个合适的条件来划分区间,也就是说不能将整个区间划分为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