LeetCode704:二分查找

49 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第14天,点击查看活动详情

题目描述

难度:简单

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

输入:整型数组 nums、搜索目标值 target
输出:搜索目标值的下标,或者-1。

算法

由题意可知,给定的待搜索数组为有序数组,对于有序数组的搜索,优先考虑二分查找来提高效率。

步骤

二分查找的思想为将整个数组分为两部分来查找,步骤如下:

  1. 每次拿目标元素与整个搜索区间的中间元素比较;
  2. 若是目标元素等于中间元素,此时目标已找到,直接返回中间元素的下标;
  3. 若是目标元素大于中间元素,则说明目标元素在右半搜索区间,此时将区间缩小为右半搜索区间,即区间左指针右移到中间元素的后一元素;(因为中间元素已经被比较过,所以缩小后的搜索区间无需包括中间元素)
  4. 若是目标元素小于中间元素,则说明目标元素在左半搜索区间,此时将区间缩小为左半搜索区间,即区间右指针左移到中间元素的前一元素;
  5. 最后若左指针大于右指针,此时区间已不存在,但是还是未找到目标元素,说明目标元素不存在于数组中,返回-1。

注意:边界条件为left = right,此时mid也与这两者重合,还需要最后判断这个边界是否符合条件,所以循环条件为left <= right。

时间复杂度和空间复杂度

时间复杂度:设整个数组的长度n<=2mn <= 2 ^ m,可以看出二分查找的比较次数为m次,又有m=log2nm = log_2 ^ n,所以时间复杂度为O(log2n)O(log_2 ^ n)
空间复杂度:只有区间的左右指针两个额外变量,为常数个额外空间,所以空间复杂度为O(1)O(1)

代码实现

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