二分搜索算法代码实现

/**
 * 二分搜索算法(包含递归与非递归)
 */
public class BinarySearch {

    public static void main(String[] args) {

//        int[] nums = {1, 3, 5, 6, 8, 9, 11};
//        int i = binarySearch2(nums, 11, 0, nums.length - 1);

//        int[] nums = {5, 7, 7, 8, 8, 10};
//        int i = searchLowerBound(nums, 8, 0, nums.length - 1);
//        int j = searchUpperBound(nums, 8, 0, nums.length - 1);

//        int[] nums = {-2, 0, 1, 4, 7, 9, 10};
//        int i = firstGreaterThan(nums, 6, 0, nums.length - 1);

        int[] nums = {4, 5, 6, 7, 0, 1, 2}; //经过旋转了的数组
        int i = binarySearchForRevolve(nums, 7, 0, nums.length - 1);
        System.out.println(i);
    }

    /**
     * 二分搜索递归写法
     * @param nums
     * @param target
     * @param low
     * @param high
     * @return
     */
    public static int binarySearch(int[] nums, int target, int low, int high){
        if(low > high) return  -1;

        int middle = low + (high - low)/2;

        if(nums[middle] == target) return middle;

        if(target < nums[middle]){
            return binarySearch(nums, target, low, middle - 1);
        }else{
            return binarySearch(nums, target, middle + 1, high);
        }
    }

    /**
     * 二分搜索非递归写法
     * @param nums
     * @param target
     * @param low
     * @param high
     * @return
     */
    public static int binarySearch2(int[] nums, int target, int low, int high){
        while (low <= high){
            int middle = low + (high - low)/2;

            if(nums[middle] == target) return middle;

            if(target < nums[middle]){
                high = middle - 1;
            }else{
                low = middle + 1;
            }
        }

        return -1;
    }

    /**
     * 二分搜索递归写法——变形(寻找下边界)
     * @param nums
     * @param target
     * @param low
     * @param high
     * @return
     */
    public static int searchLowerBound(int[] nums, int target, int low, int high){
        if(low > high) return  -1;

        int middle = low + (high - low)/2;

        if(nums[middle] == target && (middle == 0 || nums[middle - 1] < target)) return middle;

        if(target <= nums[middle]){
            return searchLowerBound(nums, target, low, middle - 1);
        }else{
            return searchLowerBound(nums, target, middle + 1, high);
        }
    }

    /**
     * 二分搜索递归写法——变形(寻找上边界)
     * @param nums
     * @param target
     * @param low
     * @param high
     * @return
     */
    public static int searchUpperBound(int[] nums, int target, int low, int high){
        if(low > high) return  -1;

        int middle = low + (high - low)/2;

        if(nums[middle] == target && (middle == nums.length - 1 || nums[middle + 1] > target)) return middle;

        if(target < nums[middle]){
            return searchUpperBound(nums, target, low, middle - 1);
        }else{
            return searchUpperBound(nums, target, middle + 1, high);
        }
    }

    /**
     * 二分搜索递归写法——变形(寻找模糊边界)
     * @param nums
     * @param target
     * @param low
     * @param high
     * @return
     */
    public static int firstGreaterThan(int[] nums, int target, int low, int high){
        if(low > high) return  -1;

        int middle = low + (high - low)/2;

        if(nums[middle] > target && (middle == 0 || nums[middle - 1] <= target)) return middle;

        if(target < nums[middle]){
            return firstGreaterThan(nums, target, low, middle - 1);
        }else{
            return firstGreaterThan(nums, target, middle + 1, high);
        }
    }

    /**
     * 二分搜索递归写法——变形(经过旋转了的数组)
     * @param nums
     * @param target
     * @param low
     * @param high
     * @return
     */
    public static int binarySearchForRevolve(int[] nums, int target, int low, int high){
        if(low > high) return  -1;

        int middle = low + (high - low)/2;

        if(nums[middle] == target) return middle;

        if(nums[low] <= nums[middle]){      //判断左半边是否排好序
            if(nums[low] <= target && target < nums[middle]){   //判断目标值是否在左半边
                return binarySearchForRevolve(nums, target, low, middle - 1);
            }
            return binarySearchForRevolve(nums, target, middle + 1, high);
        }else{
            if(nums[middle] < target && target <= nums[high]){  //判断目标值是否在右半边
                return binarySearchForRevolve(nums, target, middle + 1, high);
            }
            return binarySearchForRevolve(nums, target, low, middle - 1);
        }
    }

    /**
     * 不定长边界(先利用二分搜索思想找边界,在使用普通二分搜索)
     * @param logs
     * @param high
     * @return
     */
    public static int getUpperBound(String[] logs, int high){
        if(logs[high] == null){
            return high;
        }
        return getUpperBound(logs, high*2);
    }

    /**
     * 利用二分搜索查找日志
     * @param logs
     * @param low
     * @param high
     * @return
     */
    public static int binarySearch(String[] logs, int low, int high){
        if(low > high) return  -1;

        int middle = low + (high - low)/2;

        if(logs[middle] == null && logs[middle - 1] != null) return middle;

        if(logs[middle] == null){
            return binarySearch(logs, low, middle - 1);
        }else{
            return binarySearch(logs ,middle + 1, high);
        }
    }
}

猜你喜欢

转载自www.cnblogs.com/shlearn/p/12688572.html
今日推荐