LeetCode--704.二分查找(数组)

题目描述

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

你必须编写一个具有 O(log n) 时间复杂度的算法。

示例 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

提示:

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

解题思路

这道题目的前提是数组为有序数组 ,同时题目还强调数组中无重复元素,因为一旦有重复元素,使用二分查找法返回的元素下标可能不是唯一的,这些都是使用二分法的前提条件,当大家看到题目描述满足如上条件的时候,可要想一想是不是可以用二分法了。

二分查找涉及的很多的边界条件,逻辑比较简单,但就是写不好。例如到底是 while(left < right) 还是 while(left <= right),到底是right = middle呢,还是要right = middle - 1呢?

大家写二分法经常写乱,主要是因为对区间的定义没有想清楚,区间的定义就是不变量 。要在二分查找的过程中,保持不变量,就是在while寻找中每一次边界的处理都要坚持根据区间的定义来操作,这就是循环不变量规则。

写二分法,区间的定义一般为两种,左闭右闭即[left, right],或者左闭右开即[left, right)。

我个人倾向使用左闭右闭方法处理二分法。

如图所示,当我们使用左闭右闭即[left, right]时,就需要让right = middle - 1了。因为middle的值已经做过一次比较。

代码

java 复制代码
class Solution {
    public int search(int[] nums, int target) {
        
        int length = nums.length;
        // 左边下标初始为0
        int left = 0;
        // 记录右边下标,为数组长度 - 1
        int right = length - 1;
        // 避免当 target 小于nums[0] nums[nums.length - 1]时多次循环运算
        if (target < nums[0] || target > nums[length - 1]) {
            return -1;
        }
        // 使用左闭右闭即[left, right]区间
        while(left <= right){
             // 初始化中点 middle,以防溢出,用减法
             int middle = left + (right - left) / 2;
            // 比target大,right = middle - 1
            if(nums[middle] > target){
                right = middle - 1;
            } else if(nums[middle] < target){
                // 比target小,left = middle + 1
                left = middle + 1;
            } else{
                return middle;
            }
        }
        // 若left > right,要求的target数组中不存在
        return -1;
        
    }
}
相关推荐
xiaoye-duck2 小时前
《算法题讲解指南:动态规划算法--路径问题》--11.按摩师,12.打家劫舍II
c++·算法·动态规划
代码探秘者2 小时前
【算法篇】1.双指针
java·数据结构·人工智能·后端·python·算法
qq_417695052 小时前
C++中的中介者模式
开发语言·c++·算法
tobias.b2 小时前
计算机基础知识-操作系统
考研·面试·职场和发展
像素猎人2 小时前
pair<类型1, 类型2> 变量名的介绍,自用笔记
开发语言·c++·算法
向往着的青绿色2 小时前
完全平方数【Letcode279题解】
开发语言·c++·数学·算法·面试·性能优化·动态规划
手握风云-2 小时前
优选算法的后进之道:栈专题
算法
xwz小王子2 小时前
Science Robotics 赋予机器人“类脑”触觉,低成本视觉-触觉预训练攻克灵巧手多任务操作
人工智能·算法·机器人
Vect__2 小时前
记录3.20和3.21做过的一些力扣的思考
linux·算法·leetcode