看完这篇文章你就彻底懂啦{保姆级讲解}-----(LeetCode刷题704、35、34数组二分查找) 2023.4.17

2023-05-16

目录

    • 前言
    • 数组的定义
    • 数组的存储结构
    • 算法题(LeetCode 704.二分查找)---(保姆级别讲解)
      • 分析题目
      • 什么是二分查找?
      • 算法思想(重要)
      • 第一种写法代码:
      • 第二种写法代码(本人不推荐):
    • 算法题(LeetCode 35.二分查找)---(保姆级别讲解)
      • 分析题目
      • 算法思想(重要)
    • 算法题(LeetCode 34.二分查找)---(保姆级别讲解)
      • 分析题目
      • 算法思想(重要)
      • 分析 :
      • 反思:
      • 主体代码:
    • 结束语

前言

本文章一部分内容参考于《代码随想录》----如有侵权请联系作者删除即可,撰写本文章主要目的在于记录自己学习体会并分享给大家,全篇并不仅仅是复制粘贴,更多的是加入了自己的思考,希望读完此篇文章能真正帮助到您!!!

数组的定义

数组是由n(n>=1)个相同类型的数据元素构成的有限序列,每个数据元素称为一个数组元素,每个元素在n个线性关系中的序号称为该元素的下标,下标的取值范围为数组的维界。
在这里插入图片描述由上图可知:

  1. 数组下标都是从0开始的
  2. 数组内存空间的地址是连续的

数组的存储结构

对于多维数组,有两种映射方式,按行优先和按列优先。以二维数组为例,按行优先存储的基本思想是:先行后列,先存储行号较小的元素,行号相等先存储列号较小的元素。
在这里插入图片描述
在这里插入图片描述

算法题(LeetCode 704.二分查找)—(保姆级别讲解)

力扣题目链接
在这里插入图片描述

分析题目

  1. 处理数据类型为整型数组
  2. 该数组为有序数组即升序数组
  3. 该数组中的元素是不重复
  4. 上述条件中的2和3是我们决定使用二分查找的关键

什么是二分查找?

我们会使用有序索引数组来表示被查找的目标值target可能存在的子数组的大小范围。在查找时,我们先将被查找的目标值和子数组的中间值比较。如果被查找的目标值小于中间值,我们就在左子数组中继续查找,如果大于,我们就在右子数组中继续查找,否则中间值就是我们要找的目标

算法思想(重要)

二分查找其实有两种写法:

  1. 左闭右闭-----------[left, right]
  2. 左闭右开-----------[left, right)

*至于为什么是两种写法后面会阐述,但是在这里我想声明一点,第二种写法本人不推荐,徒增算法难度,我们学习算法的初心不是算法越难越好,而是如何用最简单的算法思想解决我们的问题,这才是最主要的。所以本篇文章不会讨论第二种,如果对第二种写法感兴趣的可以自行探索。 *

第一种写法代码:

// (写法一) 左闭右闭区间 [left, right]
int search(int* nums, int numsSize, int target){
    int left = 0;
    int right = numsSize-1;
    int middle = 0;
    
    while(left<=right) {
        middle = (left+right)/2;  
        if(nums[middle] > target) {
            right = middle-1;
        } 
        else if(nums[middle] < target) {
            left = middle+1;
        } 
        else if(nums[middle] == target){
            return middle;
        }
    } 
    return -1;
}
时间复杂度:O(log n)
空间复杂度:O(1

好!按照老样子,接下来开始详细讲解每行代码的用处,以及为什么这样写!

int search(int* nums, int numsSize, int target)

//函数入口参数分别为int* nums, int numsSize, int target,其中nums是int类型的指针,指向了其目标数组,numsSize为数组元素个数,target为数组目标值。

 int left = 0;
 int right = numsSize-1;
 int middle = 0;

//初始化部分,左边界left初始化为0(因为数组下标是从0开始的),右边界right初始化为numsSize-1(因为数组下标是从0开始的,也就是0~numsSize-1),middle初始化为0(也就是计算中间值的下标)

 while(left<=right) 

//熟悉二分查找的都应该知道最终只会有三种情况,分别是left>right,left=right,left>right,当left>right证明该算法已经遍历结束也就代表其目标数组中没有我们要寻找的目标值(target)。

 middle = (left+right)/2;  

//计算中间值下标的公式,举个例子,假设目标数组中有6个元素,即下标为0~5,那么在第一次二分查找时计算middle值为(0+5)/2 = 2,即下标为2对应的middle值与target值比较大小。

if(nums[middle] > target) {
	right = middle-1;
	} 

//根据二分查找的算法思想可知,当中间值大于target值时,意味着target值可能位于[left,middle-1]这个区间内,所以需要将right赋值为middle-1。

else if(nums[middle] < target) {
	left = middle+1;
	} 

//根据二分查找的算法思想可知,当中间值小于target值时,意味着target值可能位于[middle+1,right]这个区间内,所以需要将left赋值为middle+1。

else if(nums[middle] == target){
	return middle;
	}

//根据二分查找的算法思想可知,当中间值等于target值时,意味着当前遍历的middle下标对应的值即为我们所寻找的目标值。

 return -1;

//如果都不满足上述条件,则代表目标数组中没有我们所寻找的目标值。

为了更能让大家了解二分查找的算法思想,作者特意画了一张图供大家观看!!!
在这里插入图片描述

第二种写法代码(本人不推荐):

// (版本二) 左闭右开区间 [left, right)
int search(int* nums, int numsSize, int target){
    int length = numsSize;
    int left = 0;
    int right = length;	//定义target在左闭右开的区间里,即:[left, right)
    int middle = 0;
    while(left < right){  // left == right时,区间[left, right)属于空集,所以用 < 避免该情况
        int middle = left + (right - left) / 2;
        if(nums[middle] < target){
            //target位于(middle , right) 中为保证集合区间的左闭右开性,可等价为[middle + 1,right)
            left = middle + 1;
        }else if(nums[middle] > target){
            //target位于[left, middle)中
            right = middle ;
        }else{	// nums[middle] == target ,找到目标值target
            return middle;
        }
    }
    //未找到目标值,返回-1
    return -1;
}
时间复杂度:O(log n)
空间复杂度:O(1

//第二种写法相对于第一种写法的主要区别在于右边界right下标的选取,举个例子,初始阶段,left = 0,但是第二种写法中将right下标设置为numsSize,而不是第一种写法的numsSize-1,虽然改动了这个,但是在以后的判断中间值和target值时,会增加一些难度,例如当中间值大于target值时,意味着target值可能位于[left,middle-1]的区间内,但是由于是第二种写法,所以这里就只需将middle值赋值给right值即可,细心一点会发现和middle值小于target值的情况处理是不一样的,所以在实际的编写算法过程中容易犯错,徒增算法难度。所以第二种写法本人不推荐(没必要和自己过不去,懂得都懂)。

算法题(LeetCode 35.二分查找)—(保姆级别讲解)

力扣链接
在这里插入图片描述

分析题目

  1. 处理数据类型为整型数组
  2. 该数组为有序数组升序数组
  3. 该数组中的元素是不重复
  4. 上述条件中的2和3是我们决定使用二分查找的关键

算法思想(重要)

//版本一 [left, right]左闭右闭区间,版本二 [left, right]左闭右开区间不推荐(不推荐理由见本文章中有介绍)
int searchInsert(int* nums, int numsSize, int target){
    //左闭右开区间 [0 , numsSize-1]
        int left =0;
        int mid =0;
        int right = numsSize - 1;
        while(left <= right){
            mid = left + (right - left) / 2;
            if(target < nums[mid]){
                right = mid -1;
            }else if( target > nums[mid]){
                left = mid + 1;
            }else {
                return mid;
            }
        }
        //数组中未找到target元素
        //target在数组所有元素之后,[left, right]是右闭区间,需要返回 right +1
        return right + 1;
}

可以发现35题和704题代码大致相同,唯一一点是最后的找不到目标值,即在本题目中找不到其所需要插入的位置时,需要返回right + 1,接下来我们来细细讲一下找不到目标值的情况。
找不到目标值大致分为三种情况:

  1. 目标值在数组所有元素之前
  2. 目标值插入数组中的位置
  3. 目标值在数组所有元素之后

为了更能让大家了解找不到目标值的三种情况,作者特意画了一张图供大家观看!!!
在这里插入图片描述在这里插入图片描述

算法题(LeetCode 34.二分查找)—(保姆级别讲解)

力扣链接
在这里插入图片描述

分析题目

  1. 处理数据类型为整型数组
  2. 该数组为非递减顺序数组

算法思想(重要)

其实本题题目中已经很清楚表示最终需要找到目标值在数组中的开始位置和结束位置即该问题又可转化为寻找左边界和寻找右边界。所以接下来我们分别探讨这两个问题。
寻找左、右边界又需要考虑三种情况,如下所示:
在这里插入图片描述

  1. 寻找左边界
int getLeftBorder(vector<int>& nums, int target) {
    int left = 0;
    int right = nums.size() - 1; 
    int leftBorder = -2; 
    while (left <= right) {
        int middle = left + ((right - left) / 2);
        if (nums[middle] >= target) { 
            right = middle - 1;
            leftBorder = right;
        } else {
            left = middle + 1;
        }
    }
    return leftBorder;
}
  1. 寻找右边界
int getRightBorder(vector<int>& nums, int target) {
    int left = 0;
    int right = nums.size() - 1; 
    int rightBorder = -2; 
    while (left <= right) { 
        int middle = left + ((right - left) / 2);
        if (nums[middle] > target) {
            right = middle - 1; 
        } else { 
            left = middle + 1;
            rightBorder = left;
        }
    }
    return rightBorder;
}

分析 :

跟前面两个算法我们对比下,其实细心一点会发现最大的改变有两处,分别是:

  1. 增加了leftBorderrightBorder这两个变量,代表边界
  2. 增加了leftBorder = right;和 rightBorder = left;这两个语句。

为了更能让大家了解这两个不同之处,作者特意画了一张图供大家观看!!!

在这里插入图片描述

反思:

从前很喜欢一句话,在这里分享给大家:

告诉我,我会忘记!
给我看,我可能记住!
让我参与其中,我才会理解!

所以我就在想如果经过一段时间后,让我重新再做这道题,我还能不能完整写出来?
那么问题来了,其实和前两个算法我的思考在于两个方面,分别是(以寻找左边界为例):

  1. leftBorder = right;(为什么寻找左边界,是right赋值给leftBoder)
  2. if (nums[middle] >= target) {
    right = middle - 1;
    leftBorder = right;}(为什么leftBorder = right;这个语句在这个if语句里,而不是在else语句里)

针对上面两个思考,我给出自己的理解

  1. 寻找左边界的代码最终返回的变量是leftBoder,在该算法执行的过程中可以发现,因为寻找的是左边界问题,所以相当于是right值不断从右往左减少,即leftBoder是随着right值的趋势改变的。(寻找右边界同理)

  2. 在这里插入图片描述

主体代码:

左右边界计算完之后,看一下主体代码,这里把上面讨论的三种情况,都覆盖了

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        int leftBorder = getLeftBorder(nums, target);
        int rightBorder = getRightBorder(nums, target);
        // 情况一
        if (leftBorder == -2 || rightBorder == -2) return {-1, -1};
        // 情况三
        if (rightBorder - leftBorder > 1) return {leftBorder + 1, rightBorder - 1};
        // 情况二
        return {-1, -1};
    }
private:
     int getRightBorder(vector<int>& nums, int target) {
        int left = 0;
        int right = nums.size() - 1;
        int rightBorder = -2; // 记录一下rightBorder没有被赋值的情况
        while (left <= right) {
            int middle = left + ((right - left) / 2);
            if (nums[middle] > target) {
                right = middle - 1;
            } else { // 寻找右边界,nums[middle] == target的时候更新left
                left = middle + 1;
                rightBorder = left;
            }
        }
        return rightBorder;
    }
    int getLeftBorder(vector<int>& nums, int target) {
        int left = 0;
        int right = nums.size() - 1;
        int leftBorder = -2; // 记录一下leftBorder没有被赋值的情况
        while (left <= right) {
            int middle = left + ((right - left) / 2);
            if (nums[middle] >= target) { // 寻找左边界,nums[middle] == target的时候更新right
                right = middle - 1;
                leftBorder = right;
            } else {
                left = middle + 1;
            }
        }
        return leftBorder;
    }
};

其中针对这行代码做一些解释:

// 情况三
if (rightBorder - leftBorder > 1) return {leftBorder + 1, rightBorder - 1};

因为本算法的功能是计算出来的右边界是不包含target的右边界,左边界同理。

结束语

如果觉得这篇文章还不错的话,记得点赞 ,支持下!!!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

看完这篇文章你就彻底懂啦{保姆级讲解}-----(LeetCode刷题704、35、34数组二分查找) 2023.4.17 的相关文章

  • 【C++】9.GIS应用:开源GIS平台开发入门(MapServer+QGIS+PostGIS+OpenLayers)

    GIS地理信息处理相关 文章目录 1 GIS软件工具2 MapServer服务器3 QGIS桌面软件QGIS加载csv数据 4 PostGIS数据库5 OpenLayers JS 浏览器客户端 1 GIS软件工具 在GIS数据处理时 xff
  • 【C++】6.网络编程:socket实现通信(文字、语音)

    常见的通信方式有文本 语音 xff0c 下面用C 43 43 实现 xff1a 参考 xff1a https blog csdn net Robot hfut article details 102862052 https blog csd
  • 【ros】6.ros激光雷达SLAM(建图定位)

    百行业为先 xff0c 万恶懒为首 梁启超 文章目录 smirk 1 激光SLAM blush 2 二维激光SLAM satisfied 3 三维激光SLAM x1f60f 1 激光SLAM SLAM xff08 同步定位与地图构建 xff
  • 【ros】7.ros导航navigation(定位规划)

    物竞天择 xff0c 优胜劣汰 xff1b 苟不自新 xff0c 何以获存 梁启超 文章目录 smirk 1 ros导航 blush 2 2d导航 satisfied 3 3d导航 x1f60f 1 ros导航 ros机器人有个导航功能 x
  • 【两周年】我的创作纪念日(水)

    机缘 两年前的今天 xff0c 处于离职状态 xff0c 准备去另一个城市工作 xff0c 同时开始学习编程知识 IT技能 xff0c CSDN让我发现了一群热爱学习和分享的小伙伴 xff0c 也萌发了在这里扎根的想法 收获 不知不觉已经两
  • AI模型部署概述

    心口如一 xff0c 犹不失为光明磊落丈夫之行也 梁启超 文章目录 smirk 1 AI模型部署方法 blush 2 AI模型部署框架ONNXNCNNOpenVINOTensorRTMediapipe如何选择 satisfied 3 AI模
  • 【C++】1.语言基础:八股文

    心口如一 xff0c 犹不失为光明磊落丈夫之行也 梁启超 文章目录 smirk 1 语言基础内存分配指针参数传递和引用参数传递四种强制转换面向对象的三大特性并举例 define 和别名 typedef 的区别 blush 2 标准库STL介
  • 【VSLAM】ORB-SLAM3安装部署与运行

    心口如一 xff0c 犹不失为光明磊落丈夫之行也 梁启超 文章目录 smirk 1 ORB SLAM3介绍 blush 2 代码安装部署1 安装ros与opencv2 安装Pangolin作为可视化和用户界面3 安装Eigen3一个开源线性
  • 【Linux运维】ACPI BIOS Error问题解决

    今天帮朋友装个ubuntu系统 xff0c 遇到一个问题记录一下 报错与现象 xff1a ACPI BIOS Error 电脑花屏 解决方法 xff1a 插入启动盘 xff0c 当进入引导界面后 xff0c 键盘输入 e xff0c 编辑L
  • catkin_make的时候发生了什么

    原链接http community bwbot org topic 182 运行测试平台 小强ROS机器人 这是一个比较复杂的问题 xff0c 但是有时候会有莫名其妙的编译错误 xff0c 在找错误的过程中会非常需要了解这个过程 首先说一下
  • 【ros】8.有限状态机

    心口如一 xff0c 犹不失为光明磊落丈夫之行也 梁启超 文章目录 smirk 1 有限状态机认识 blush 2 一个简单的示例 satisfied 3 自动驾驶如何用有限状态机 x1f60f 1 有限状态机认识 有限状态机 xff08
  • 【C++】8.编译:CMake工具入门

    x1f60f xffe3 xffe3 x1f60f 这篇文章主要介绍CMake工具的入门使用 学其所用 xff0c 用其所学 梁启超 欢迎来到我的博客 xff0c 一起学习知识 xff0c 共同进步 x1f95e 喜欢的朋友可以
  • lwip --- (十六)TCP建立流程

    这一节我们就看看如何在我们的LWIP上实现一个http服务器的过程 xff0c 结合连接建立过程来理解TCP状态转换图和TCP控制块中各个字段的意义 这里先讲解一些与TCP相关的最基础的函数 xff0c 至于是怎样将这些函数合理高效的组织起
  • TCP和串口间的互相通信(透传)

    TCP和串口间的互相通信 xff08 透传 xff09 Tcp作为服务端 xff0c 接收消息 xff0c 通过串口发送 span class token keyword private span span class token retu
  • CONTINUING||重启

    现在是20年的8月13日 这是一个让自己非常难忘的一天 此时的我已经实现了当时自己曾经许下的诺言 xff0c 实现了自己当时年少无知的梦想 找到了一个好公司 xff0c 有了一份好工作 xff08 tx xff09 但是这不是自己的梦想的终
  • c语言| |strstr函数的源代码以及自我实现

    strstr函数 strstr函数 xff1a strstr str1 str2 函数用于判断字符串str2是否是str1的子串 如果是 xff0c 则该函数返回str2在str1中首次出现的地址 xff1b 否则 xff0c 返回NULL
  • 如何在Linux下用vim编写代码

    1 首先进入到一个目录下 xff0c 输入命令 vim test c 2 便会在该目录下 xff0c 创建一个test c xff08 test c不存在 xff09 的文件 xff0c 如果test c存在的话 xff0c 那么就打开该文
  • C语言| |c语言下如何输出彩色的字

    c语言下如何输出彩色的字 使用格式 xff1a 样式开始 43 被修饰字符串 43 样式结束 样式开始 xff1a 033 43 参数1 43 xff1a 43 参数2 43 xff1a 43 参数3 43 m 参数1 xff1a 代表背景
  • Linux| |对于UDP的学习

    UDP 前序 UDP xff08 用户数据报协议 xff09 没有连接的 xff0c 是面向数据报的 xff0c 是不可靠 套接字 就是IP地址 43 端口号 IP地址 xff1a 4字节 端口号 xff1a 2字节 xff0c 也就是说范
  • 数据结构| |各类排序的时间复杂度以及稳定性

    各类排序的时间复杂度以及稳定性 插入排序 xff1a 直接插入排序 xff1a O N 2 稳定 希尔排序 xff1a O N 1 3 不稳定 选择排序 xff1a 选择排序 xff1a O N 2 不稳定 堆排序 xff1a O Nlog

随机推荐

  • 安装Nvidia显卡驱动和CUDA

    原链接 http community bwbot org topic 152 网上看到的 xff0c 但是原链接 不过这里安装的是CUDA7 5 xff0c 现在最新的是8 0 可以到官网进行下载 xff0c 记住一定不要选择deb方式 x
  • Linux| |IP地址的三类私有地址

    IP地址的三类私有地址 对于IP地址来说有着三种私有地址 三种私有地址如下 xff1a 10 0 0 0 10 255 255 255 172 16 0 0 172 16 255 255 192 168 0 0 192 168 255 25
  • Linux| |如何高效切换目录

    Linxu如何高效切换目录 前言 Linux下对于目录的切换 xff0c 大家肯定会想到一个命令 xff1a cd命令 cd命令确实方便 xff0c 但是当需要频繁的切换目录的时候 xff0c cd命令可能比较麻烦了 比如 xff1a ho
  • C++| |四种强制类型转化(剖析)

    四种强制类型转换 1 出现的原因 C语言的强制类型转换 xff0c 有着两种 隐式类型转换 显示的强制类型转换 举例 xff1a int main int i 61 1 double d 61 i 隐式类型转换 int p 61 amp i
  • 数据结构| |快速排序,二路快排,三路快排

    快速排序 二路快排 三路快排 1 快速排序 1 概念 快速排序采用分治的思想对数据进行排序 选择一个基准值 将比基准值小的放在基准值的左边 xff0c 其余的 xff08 大于或者等于 xff09 放在右边 然后再对左边和右边继续进行划分
  • socket编程中write、read和send、recv

    write xff08 xff09 与read xff08 xff09 函数send xff08 xff09 与recv xff08 xff09 函数 一旦 xff0c 我们建立好了tcp连接之后 xff0c 我们就可以把得到的fd当作文件
  • Ubuntu上火狐浏览器无法上网的解决方法

    网上有的方法是在浏览器中选择更新 xff0c 后来找到了更加直接好用的方法 xff0c 只需要几行命令就可以 1 在终端中输入sudo apt get update 如果在这一步出现错误 xff0c 显示暂时不能解析域名的情况 xff0c
  • 实现字符串连接函数(strcat)

    在字符串的操作中strcat函数的使用是频繁的 xff0c 那么下面我们来自己实现strcat函数的功能 自定义一个函数将要连接的两个字符串作为参数传入 xff0c 然后将str1赋值给临时变量p 然后p一直向后指 xff0c 直到str1
  • C#开发简单的串口上位机

    采用C 开发上位机非常方便 xff0c 具体步骤如下 xff1a 1 绘制一个上位机的界面 xff0c 如下图所示 xff1a 不要忘记还有下面的串口模块serialPort1 2 初始化部分 xff1a 波特率编辑框中加入需要的波特率 实
  • STM32读取匿名光流数据——与Guidance的光流和超声波做对比测试

    使用两个串口同时读取匿名光流和Guidance数据 xff1a 用以比较两个光流的效果 Github链接 xff1a https github com W yt YuTian Pro tree master Guidance 26Ano R
  • UDP编程笔记

    1 字节序 1 1 概念 是指多字节数据的存储顺序 1 2 分类 小端格式 xff1a 将低位字节数据存储在低地址 大端格式 xff1a 将高位字节数据存储在低地址 1 3 注意 LSB xff1a 低地址 MSB xff1a 高地址 2
  • rviz的简单使用

    原链接 xff1a http community bwbot org 运行测试平台 小强ROS机器人 rviz是ros自带的一个图形化工具 xff0c 可以方便的对ros的程序进行图形化操作 其使用也是比较简单 整体界面如下图所示 界面主要
  • c语言_结构体封装寄存器的用法,以及typedef、 volatile、static、 inline关键字用法

    define span class token constant ELFIN TIMER BASE span span class token number 0xE2500000 span span class token comment
  • Ros—RPLIDAR A2激光雷达安装(hector_mapping算法建图同cartographer_ros建图对比)

    Ros RPLIDAR A2激光雷达安装 hector mapping算法建图同cartographer ros建图对比 因为大部分教程复杂繁琐 xff0c 而且容易失败 便整理总结了一下网上的资料 xff0c 感谢 Cayla和 口袋里的
  • 海康设备xml透传以及DS-K1F100-D8E 设备下发卡 ,读卡

    对接海康5604设备 设置温度上限及下限 设备较多通过demo手动透传不可取 故采用代码方式进行透传 代码记录 方便后续开发找方便 public void setThermal Map lt String Object gt params
  • ROS学习之error解决记录

    目录 虚拟机系统版本 xff1a Ubuntu 20 04 ROS版本 xff1a Noetic 1 15 14 虚拟机系统版本 xff1a Ubuntu 18 04 ROS版本 xff1a Melodic 1 14 13 整理一下平时遇到
  • C语言 带参数的#define中#和##的基本用法

    1 单 的作用是把参数变成字符串 xff1b 2 的作用是连接组合参数名字 xff1b 废话不多说 xff0c 看个简洁的例子就明白了 span class token macro property span class token dir
  • 类的封装--- 2021.10.19

    封装是什么 xff1f 我们都知道C 43 43 有三大特性 xff0c 分别是继承 多态和封装 至于继承和多态我会在之后的文章中进行讲述 xff0c 在本讲中我们只讲类的封装 在上一讲中 xff0c 我们论述了类是什么 xff0c 那么我
  • 队列的链式存储--- 2021.10.27

    上一讲链接 xff1a 队列的基本概念 2021 10 8 队列的链式存储 xff1a 什么叫队列的链式存储呢 xff1f 我们在上一讲都知道队列的结构特点 xff0c 那么我们可不可以通过链表来实现队列 xff0c 从而实现了队列的链式存
  • 看完这篇文章你就彻底懂啦{保姆级讲解}-----(LeetCode刷题704、35、34数组二分查找) 2023.4.17

    目录 前言数组的定义数组的存储结构算法题 xff08 LeetCode 704 二分查找 xff09 xff08 保姆级别讲解 xff09 分析题目什么是二分查找 xff1f 算法思想 xff08 重要 xff09 第一种写法代码 xff1