数组-二分查找

177 阅读2分钟

同一个解决问题的思路下有多个题目

1、题目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]之间。

代码示例:

private static int binarySearch(int[] nums, int target) {
    int left = 0;
    int right = nums.length-1;
    while (left <= right) {
        int mid = (left + right)/2;  // 可以改写为left + (right-left)/2
        if (nums[mid] == target) {
            return mid;
        } else if (nums[mid] < target) {
            left = mid + 1;
        } else if (nums[mid] > target) {
            right = mid - 1;
        }
    }
    return -1;
}

2、题目2-判断一个数是否是完全平方数

给定一个 正整数 num ,编写一个函数,如果 num 是一个完全平方数,则返回 true ,否则返回 false 。 进阶:不要 使用任何内置的库函数,如  sqrt 。 示例 1:

输入: num = 16
输出: true

示例 2:

输入: num = 14
输出: false

代码实现:

private static boolean mySqrt(int x) {
    int left = 1;
    int right = x;
    if (x < 2) {
        return true;
    }
    boolean isPerfectSquare = false;
    while (left <= right){
        // 使用 left + (right - left) / 2写法是防止溢出,比如right=2147483647,如果直接使用(right+left)/2,分子就会直接溢出
        int middle = left + (right - left) / 2;
        if (((long) middle * middle) == x) {
            isPerfectSquare = true;
            break;// 跳出判断
        } else if ((long) middle * middle < x) {
            left = middle + 1;
        } else {
            right = middle - 1;
        }
    }
    return isPerfectSquare;
}

3、题目3-搜索插入位置

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

请必须使用时间复杂度为 O(log n) 的算法。

示例 1:

输入: nums = [1,3,5,6], target = 5
输出: 2

示例 2:

输入: nums = [1,3,5,6], target = 2
输出: 1

示例 3:

输入: nums = [1,3,5,6], target = 7
输出: 4

示例 4:

输入: nums = [1,3,5,6], target = 0
输出: 0

示例 5:

输入: nums = [1], target = 0
输出: 0

提示:

  • 1 <= nums.length <= 104
  • -104 <= nums[i] <= 104
  • nums 为无重复元素的升序排列数组
  • -104 <= target <= 104

代码实现:

public static int searchInsert(int[] nums, int target) {
    int right = nums.length - 1;
    int left = 0;
    int minIndex = left;
    while (left <= right) {
        int middle = (left + right)/2;
        if (nums[middle] == target) {
            return middle;
        } else if (nums[middle] < target) {
            left = middle + 1;
        } else if (nums[middle] > target) {
            right = middle - 1;
        }
        minIndex = left;
    }
    return minIndex;
}

4、题目4-Sqrt(x)

给你一个非负整数 x ,计算并返回 x 的 算术平方根 。 由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。

注意:不允许使用任何内置指数函数和算符,例如 pow(x, 0.5) 或者 x ** 0.5 。

示例 1:

输入:x = 4
输出:2

示例 2:

输入:x = 8
输出:2
解释:8 的算术平方根是 2.82842..., 由于返回类型是整数,小数部分将被舍去。

提示:

  • 0 <= x <= 231 - 1

代码示例:

private static boolean mySqrt(int x) {
    int left = 1;
    int right = x;
    if (x < 2) {
        return true;
    }
    boolean isPerfectSquare = false;
    while (left <= right){
        // 使用 left + (right - left) / 2写法是防止溢出,比如right=2147483647,如果直接使用(right+left)/2,分子就会直接溢出
        int middle = left + (right - left) / 2;
        if (((long) middle * middle) == x) {
            isPerfectSquare = true;
            break;// 跳出判断
        } else if ((long) middle * middle < x) {
            left = middle + 1;
        } else {
            right = middle - 1;
        }
    }
    return isPerfectSquare;
}