刷题--二分法(3)

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

猜你喜欢

转载自www.cnblogs.com/2333wzl/p/12244985.html