刷题日记——二分查找

32 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 2 天,点击查看活动详情

今天刷一道力扣上简单的算法题,毕竟我是小白,从基础刷起,一步一个脚印

704. 二分查找

力扣题目链接(opens new window)

给定一个 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]之间。

首先我自己做了一遍,当然这不是二分查找,只是最简单的遍历查找。

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

那么下面进入正题,如何用二分查找法来解决这道题?

前提

首先我们需要知道一个前提,可以看到题目中说数组是有序数组,并且有一句提示很明确:你可以假设 nums 中的所有元素是不重复的。因为一旦有重复元素存在的话,我们使用二分法返回的元素下标可能就不是唯一的了。

因此,当我们在看到题目中有以上的这些限制条件时,就可以考虑是不是应该用二分法解决的时候了

问题

在写二分法时,困扰我最大的其实就是关于left<right 还是left<= right,以及left=middle+1还是middle这种问题。

关于区间的写法有两种,一种是两头闭,一种是左闭右开,这两种是比较大众的,假如我们写左闭右闭的区间,也就是[left, right],那么规则就如下了

  • while (left <= right) 要使用 <= ,因为这里left == right是有意义的,所以使用 <=
  • if (nums[middle] > target) right 要赋值为 middle - 1,因为这里这个nums[middle]一定不是target,那么接下来要查找的左区间结束的下标位置就是 middle - 1

那么假如我们写的是左闭右开的区间,也就是[left, right) ,那么规则就变成了下面这样

  • while (left < right),这里使用 < ,因为这里left == right在区间[left, right)是没有意义的
  • if (nums[middle] > target) right 赋值为 middle,因为这里nums[middle]不等于target,去左区间继续寻找,而寻找区间是左闭右开区间,所以right更新为middle,即:下一个查询区间不会去比较nums[middle]

经过以上的学习,就可以独立写出下面的代码啦

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

可以看到大大减少了用时

image.png

这道题理解了二分查找的思路后,问题就迎刃而解了,没有涉及到java高级语法,所以今天没有学到语法,但是收获了算法,也是不小的收获。