leetcode 704.二分查找

143 阅读1分钟

每日刷算法

题目描述

给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。

示例 1:

输入: nums = [-1,0,3,5,9,12], target = 9 输出: 4 解释: 9 出现在 nums 中并且下标为 4 示例 2:

输入: nums = [-1,0,3,5,9,12], target = 2 输出: -1 解释: 2 不存在 nums 中因此返回 -1  

提示

你可以假设 nums 中的所有元素是不重复的。 n 将在 [1, 10000]之间。 nums 的每个元素都将在 [-9999, 9999]之间。

解题

这两点明确的告诉我们可以使用二分查找

1.最常规的遍历

for(int i=0;i<nums.length;i++) {
            if (target == nums[i]) {
                return i;
            }
        }
        return -1;

2.二分查找

规定当前数组的左右边界,然后进行while循环,直到左边大于右边

目标值与中值进行比较,等于或者选择分组,然后循环进分组.(注意,分组的另一端边界需要与中值+1/-1,否则会无限递归)

// 左右代表选择的数组的范围,最大和最小
        int left = 0;
        int right = nums.length -1;
        // 只有小于不够,只有一个元素的话需要等于
        while(left <= right) {
            // 取中间值
            int mid = (left + right);
            // 中间值进行比较,决定去哪个分组
            if (target == nums[mid]) {
                return mid;
            }else if (target < nums[mid]) {
                // 左右的边界值都需要-1和+1,否则会无限循环
                right = mid - 1;
            }else {
                left = mid + 1;
            }
        }
        return -1;

可以对mid进行优化,为防止溢出,可以这么写

int middle = left + ((right - left) / 2)

3.Arrays 方法类集成了方法,我们来看一下源码

private static int binarySearch0(long[] a, int fromIndex, int toIndex,
                                     long key) {
        int low = fromIndex;
        int high = toIndex - 1;

        while (low <= high) {
            int mid = (low + high) >>> 1;
            long midVal = a[mid];

            if (midVal < key)
                low = mid + 1;
            else if (midVal > key)
                high = mid - 1;
            else
                return mid; // key found
        }
        return -(low + 1);  // key not found.
    }