「力扣」第 704 题:二分查找

地址:https://leetcode-cn.com/problems/binary-search/

原始二分查找实现:循环

Java 代码:

public class Solution {

    public int search(int[] nums, int target) {
        int len = nums.length;
        if (len == 0) {
            return -1;
        }
        // 在 [left, right] 区间里查找 target
        int left = 0;
        int right = len - 1;
        while (left <= right) {

            int mid = (left + right) / 2;

            if (nums[mid] == target) {
                return mid;
            } else if (nums[mid] > target) {
                // 下一轮搜索区间:[left, mid - 1]
                right = mid - 1;
            } else {
                // 此时:nums[mid] < target
                // 下一轮搜索区间:[mid + 1, right]
                left = mid + 1;
            }
        }
        return -1;
    }
}

原始二分查找实现:递归

Java 代码:

public class Solution {

    public int search(int[] nums, int target) {
        int len = nums.length;
        if (len == 0) {
            return -1;
        }
        return binarySearch(nums, target, 0, len - 1);
    }

    /**
     * 在数组 arr 的子区间 [left, right] 里搜索目标元素
     *
     * @param arr    数组
     * @param target 目标元素
     * @param left   左边界索引,包括 left
     * @param right  右边界索引,包括 right
     * @return
     */
    private int binarySearch(int[] arr, int target, int left, int right) {
        // 先处理递归到底的情况
        if (left > right) {
            // 不能形成区间,返回 -1 表示没有找到
            return -1;
        }
        int mid = (left + right) / 2;
        if (target == arr[mid]) {
            // 找到了,就将目标元素的索引返回
            return mid;
        } else if (target < arr[mid]) {
            // 既然是有序数组,目标元素的值比中间元素还要小,就应该在中间元素的左边去找
            return binarySearch(arr, target, left, mid - 1);
        } else {
            // 既然是有序数组,目标元素的值比中间元素还要大,就应该在中间元素的右边去找
            return binarySearch(arr, target, mid + 1, right);
        }
    }
}

“减治法”二分查找

把等于元素放在最后判断的二分查找算法。

注意:看到 left = mid; 取中间数的时候要加 1

  • 实现 1:

Java 代码:

public class Solution {

    public int search(int[] nums, int target) {
        int len = nums.length;

        int left = 0;
        int right = len - 1;

        while (left < right) {
            // 注意:根据分支逻辑,需要在取中间数的时候,向上取整
            int mid = (left + right + 1) >>> 1;

            if (nums[mid] > target) {
                // 下一轮搜索区间是:[left, mid - 1]
                right = mid - 1;
            } else {
                // 此时 nums[mid] <= target
                // mid 的左边一定不等于目标元素
                // 下一轮搜索区间是:[mid, right]
                left = mid;
            }
        }
        // 不要忘了单独做判断
        if (nums[left] == target) {
            return left;
        }
        return -1;
    }
}
  • 实现 2:

Java 代码:

public class Solution {

    public int search(int[] nums, int target) {
        int len = nums.length;
        int left = 0;
        int right = len - 1;
        while (left < right) {

            int mid = (left + right) >>> 1;

            if (nums[mid] < target) {
                // 下一轮搜索区间是:[mid + 1, right]
                left = mid + 1;
            } else {
                // 此时 nums[mid] >= target,
                // mid 的右边一定不存在 target,下一轮搜索区间是:[left, mid]
                right = mid;
            }
        }
        // 不要忘了单独做判断
        if (nums[left] == target) {
            return left;
        }
        return -1;
    }
}

你可能感兴趣的:(「力扣」第 704 题:二分查找)