当前位置: 首页 > news >正文

初识算法——二分查找

1.概念

二分查找算法也称折半查找,是一种非常高效的工作于有序数组的查找算法。

需求:在有序数组 A A A 内,查找值 t a r g e t target target

  • 如果找到返回索引
  • 如果找不到返回 − 1 -1 1
前提给定一个内含 n n n 个元素的有序数组 A A A,满足 A 0 ≤ A 1 ≤ A 2 ≤ ⋯ ≤ A n − 1 A_{0}\leq A_{1}\leq A_{2}\leq \cdots \leq A_{n-1} A0A1A2An1,一个待查值 t a r g e t target target
1设置 i = 0 i=0 i=0 j = n − 1 j=n-1 j=n1
2如果 i > j i \gt j i>j,结束查找,没找到
3设置 m = f l o o r ( i + j 2 ) m = floor(\frac {i+j}{2}) m=floor(2i+j) m m m 为中间索引, f l o o r floor floor 是向下取整( ≤ i + j 2 \leq \frac {i+j}{2} 2i+j 的最小整数)
4如果 t a r g e t < A m target < A_{m} target<Am 设置 j = m − 1 j = m - 1 j=m1,跳到第2步
5如果 A m < t a r g e t A_{m} < target Am<target 设置 i = m + 1 i = m + 1 i=m+1,跳到第2步
6如果 A m = t a r g e t A_{m} = target Am=target,结束查找,找到了

2.基础版

public static int binarySearch(int[] arr, int target) {int min = 0, max = arr.length - 1;while (min <= max) {int mid = (max + min) >>> 1;//无符号右移int midVal = arr[mid];if (target < midVal) {max = mid - 1;} else if (midVal < target) {min = mid + 1;} else {return mid;}}return -1;
}

3.改动版

public static int binarySearch(int[] arr, int target) {int min = 0, max = arr.length;while (min < max) {int mid = (max + min) >>> 1;//无符号右移int midVal = arr[mid];if (target < midVal) {max = mid;} else if (midVal < target) {min = mid + 1;} else {return mid;}}return -1;
}

4.衡量算法的好坏

对比线性查找
for (int i = 0; i < arr.length; i++) {if(arr[i] == target){return i;}
}
return -1;
事前分析法

在这里插入图片描述
图形计算器
在这里插入图片描述

计算机科学中,时间复杂度是用来衡量:一个算法的执行,随数据规模增大,而增长的时间成本

  • 不依赖于环境因素

如何表示时间复杂度呢?

  • 假设算法要处理的数据规模是 n n n,代码总的执行行数用函数 f ( n ) f(n) f(n) 来表示,例如:

    • 线性查找算法的函数 f ( n ) = 3 ∗ n + 3 f(n) = 3*n + 3 f(n)=3n+3
    • 二分查找算法的函数 f ( n ) = ( f l o o r ( l o g 2 ( n ) ) + 1 ) ∗ 5 + 4 f(n) = (floor(log_2(n)) + 1) * 5 + 4 f(n)=(floor(log2(n))+1)5+4
  • 为了对 f ( n ) f(n) f(n) 进行化简,应当抓住主要矛盾,找到一个变化趋势与之相近的表示法

O O O 表示法

在这里插入图片描述

其中

  • c , c 1 , c 2 c, c_1, c_2 c,c1,c2 都为一个常数
  • f ( n ) f(n) f(n) 是实际执行代码行数与 n 的函数
  • g ( n ) g(n) g(n) 是经过化简,变化趋势与 f ( n ) f(n) f(n) 一致的 n 的函数
渐进上界

渐进上界(asymptotic upper bound):从某个常数 n 0 n_0 n0开始, c ∗ g ( n ) c*g(n) cg(n) 总是位于 f ( n ) f(n) f(n) 上方,那么记作 O ( g ( n ) ) O(g(n)) O(g(n))

  • 代表算法执行的最差情况

例1

  • f ( n ) = 3 ∗ n + 3 f(n) = 3*n+3 f(n)=3n+3
  • g ( n ) = n g(n) = n g(n)=n
  • c = 4 c=4 c=4,在 n 0 = 3 n_0=3 n0=3 之后, g ( n ) g(n) g(n) 可以作为 f ( n ) f(n) f(n) 的渐进上界,因此表示法写作 O ( n ) O(n) O(n)

例2

  • f ( n ) = 5 ∗ f l o o r ( l o g 2 ( n ) ) + 9 f(n) = 5*floor(log_2(n)) + 9 f(n)=5floor(log2(n))+9
  • g ( n ) = l o g 2 ( n ) g(n) = log_2(n) g(n)=log2(n)
  • O ( l o g 2 ( n ) ) O(log_2(n)) O(log2(n))

已知 f ( n ) f(n) f(n) 来说,求 g ( n ) g(n) g(n)

  • 表达式中相乘的常量,可以省略,如
    • f ( n ) = 100 ∗ n 2 f(n) = 100*n^2 f(n)=100n2 中的 100 100 100
  • 多项式中数量规模更小(低次项)的表达式,如
    • f ( n ) = n 2 + n f(n)=n^2+n f(n)=n2+n 中的 n n n
    • f ( n ) = n 3 + n 2 f(n) = n^3 + n^2 f(n)=n3+n2 中的 n 2 n^2 n2
  • 不同底数的对数,渐进上界可以用一个对数函数 log ⁡ n \log n logn 表示
    • 例如: l o g 2 ( n ) log_2(n) log2(n) 可以替换为 l o g 10 ( n ) log_{10}(n) log10(n),因为 l o g 2 ( n ) = l o g 10 ( n ) l o g 10 ( 2 ) log_2(n) = \frac{log_{10}(n)}{log_{10}(2)} log2(n)=log10(2)log10(n),相乘的常量 1 l o g 10 ( 2 ) \frac{1}{log_{10}(2)} log10(2)1 可以省略
  • 类似的,对数的常数次幂可省略
    • 如: l o g ( n c ) = c ∗ l o g ( n ) log(n^c) = c * log(n) log(nc)=clog(n)
常见大 O O O 表示法

在这里插入图片描述

按时间复杂度从低到高

  • 黑色横线 O ( 1 ) O(1) O(1),常量时间,意味着算法时间并不随数据规模而变化
  • 绿色 O ( l o g ( n ) ) O(log(n)) O(log(n)),对数时间
  • 蓝色 O ( n ) O(n) O(n),线性时间,算法时间与数据规模成正比
  • 橙色 O ( n ∗ l o g ( n ) ) O(n*log(n)) O(nlog(n)),拟线性时间
  • 红色 O ( n 2 ) O(n^2) O(n2) 平方时间
  • 黑色朝上 O ( 2 n ) O(2^n) O(2n) 指数时间
  • 没画出来的 O ( n ! ) O(n!) O(n!)
空间复杂度

与时间复杂度类似,一般也使用大 O O O 表示法来衡量:一个算法执行随数据规模增大,而增长的额外空间成本

二分查找性能

下面分析二分查找算法的性能

时间复杂度

  • 最坏情况: O ( log ⁡ n ) O(\log n) O(logn)
  • 最好情况:如果待查找元素恰好在数组中央,只需要循环一次 O ( 1 ) O(1) O(1)

空间复杂度

  • 需要常数个指针 i , j , m i,j,m i,j,m,因此额外占用的空间是 O ( 1 ) O(1) O(1)

5.平衡版

思想:

  1. 左闭右开的区间, i i i 指向的可能是目标,而 j j j 指向的不是目标
  2. 不奢望循环内通过 m m m 找出目标, 缩小区间直至剩 1 个, 剩下的这个可能就是要找的(通过 i i i
    • j − i > 1 j - i > 1 ji>1 的含义是,在范围内待比较的元素个数 > 1
  3. 改变 i i i 边界时,它指向的可能是目标,因此不能 m + 1 m+1 m+1
  4. 循环内的平均比较次数减少了
  5. 时间复杂度 Θ ( l o g ( n ) ) \Theta(log(n)) Θ(log(n))
public static int binarySearch(int[] arr, int target) {int min = 0, max = arr.length;while (1 < max - min) {int mid = (min + max) >>> 1;if (target < arr[mid]) {max = mid;} else {min = mid;}}return (arr[min] == target) ? min : -1;
}

6.Leftmost 查询最左侧重复元素

public static int leftMost(int[] arr, int target) {int min = 0, max = arr.length - 1;int result = -1;//记录候选位置while (min <= max) {int mid = (min + max) >>> 1;int midVal = arr[mid];if (target < midVal) {max = mid - 1;} else if (midVal < target) {min = mid + 1;} else {result = mid;max = mid - 1;}}return result;
}
返回 >=target 的最靠左索引
  • leftmost 返回值的另一层含义: < t a r g e t \lt target <target 的元素个数
  • 小于等于中间值,都要向左找
public static int leftMost(int[] arr, int target) {int min = 0, max = arr.length - 1;while (min <= max) {int mid = (min + max) >>> 1;if (target <= arr[mid]) {max = mid - 1;} else {min = mid + 1;}}//返回 >=target 的最靠左索引return min;
}

7.Rightmost 查询最右侧重复元素

public static int rightMost(int[] arr, int target) {int min = 0, max = arr.length - 1;int result = -1;while (min <= max) {int mid = (min + max) >>> 1;int midVal = arr[mid];if (target < midVal) {max = mid - 1;} else if (midVal < target) {min = mid + 1;} else {result = mid;min = mid + 1;}}return result;
}
返回<=target 的最靠右索引

大于等于中间值,都要向右找

public static int rightMost(int[] arr, int target) {int min = 0, max = arr.length - 1;while (min <= max) {int mid = (min + max) >>> 1;if(target < arr[mid]){max = mid - 1;}else{min = mid + 1;}}//返回<=target 的最靠右索引return min - 1;
}

8.Leetcode 练习

  • 704题
  • 35题
  • 34题

相关文章:

初识算法——二分查找

1.概念 二分查找算法也称折半查找&#xff0c;是一种非常高效的工作于有序数组的查找算法。 需求&#xff1a;在有序数组 A A A 内&#xff0c;查找值 t a r g e t target target 如果找到返回索引如果找不到返回 − 1 -1 −1 前提给定一个内含 n n n 个元素的有序数组…...

深入剖析 Java Spring 中的 @Autowired、@Resource、@Qualifier、@Inject 注解:使用详解与注意事项

文章目录 Autowired&#xff1a;Spring 最常用的注解1. 作用与简介2. 使用示例3. 注意事项 Resource&#xff1a;按名称注入的利器1. 作用与简介2. 使用示例3. 注意事项 Qualifier&#xff1a;解决多 bean 注入问题1. 作用与简介2. 使用示例3. 注意事项 Inject&#xff1a;标准…...

ThingsBoard规则链节点:Delete Attributes节点详解

引言 删除属性节点简介 用法 含义 应用场景 实际项目运用示例 智能家居安全系统 物流跟踪解决方案 工业自动化生产线 结论 引言 ThingsBoard是一个开源的物联网平台&#xff0c;它提供了设备管理、数据收集与处理以及实时监控等功能。其中&#xff0c;规则引擎是其核心…...

关于作为面试官以及如何准备面试的一些心得

关于作为面试官以及如何准备面试的一些心得 一、面试官&#xff08;我站在前端角度来说&#xff09; 当作为这样身份的时候&#xff0c;我想第一步应该是自己梳理一些从简到难、从点到面的问题 CSS - JS - 框架 - 项目 从这四个角度出发&#xff0c;一步一步的引导面试者的思…...

Bean对象 和 普通对象 的区别

Bean对象 和 普通对象 的区别 前言Bean的概念与new创建的对象的区别Spring Bean的优势两者使用的关键点总结 前言 在Spring框架中&#xff0c;我们通常将Spring容器管理的对象称为“Bean”或“Bean对象”。而通过new关键字创建的对象则被称为“对象”或“普通对象”。 Bean的…...

lego-loam featureAssociation 源码注释(二)

咱们接着往下看initializationValue();&#xff01;&#xff01;&#xff01; FeatureAssociation():nh("~"){subLaserCloud nh.subscribe<sensor_msgs::PointCloud2>("/segmented_cloud", 1, &FeatureAssociation::laserCloudHandler, this);s…...

Claude 3.5 的六大应用场景

Claude 3.5 的六大应用场景 随着人工智能技术的飞速发展&#xff0c;Claude 3.5 已经成为一款强大的语言模型工具&#xff0c;在多个领域展现了其卓越的应用潜力。本文将通过CSDN格式&#xff0c;介绍Claude 3.5在六大主要领域的实际应用场景&#xff0c;帮助开发者和企业更好…...

进程线程知识总结

1. 程序什么时候应该使用线程&#xff0c;什么时候单线程效率高 使用线程&#xff1a;在I/O密集型或高并发的场景&#xff0c;例如网络服务、文件读写等。通过多线程可以同时处理多个任务&#xff0c;提高利用率。单线程效率高&#xff1a;在CPU密集型任务中&#xff0c;当任务…...

Rsync数据复制/备份服务应用

文章目录 1. rsync概述1.1 什么是Rsync1.2 rsync的功能1.3 rsync 的功能特性1.4 Rsync 增量复制原理1.5 生产场景架构集群备份方案 2. Rsync工作方式介绍与实践2.1 本地数据传输模式2.1.1 本地数据传输模式语法2.1.2 本地数据传输模式实践 2.2 远程Shell 数据传输模式2.2.1 远程…...

如何为自己的跨境网站添加多国语言翻译功能及推荐起尔网定制与插件开发

如何为自己的跨境网站添加多国语言翻译功能及推荐起尔网定制与插件开发 在全球化的浪潮下&#xff0c;跨境电商成为越来越多企业拓展国际市场的重要途径。然而&#xff0c;语言障碍成为了一个不可忽视的问题。为了更好地服务全球用户&#xff0c;为自己的跨境网站添加多国语言…...

安全见闻(3)——开阔眼界,不做井底之蛙

内容预览 ≧∀≦ゞ 安全见闻三&#xff1a;脚本程序与病毒声明导语脚本语言BAT/PowerShell脚本木马与宏病毒脚本病毒BIOS病毒 结语 安全见闻三&#xff1a;脚本程序与病毒 声明 学习视频来自B站UP主 泷羽sec,如涉及侵权马上删除文章 笔记的只是方便各位师傅学习知识,以下网站只…...

MySQL 的意向锁(Intention Locks)原理详解

1. 背景&#xff1a;为什么需要意向锁&#xff1f; MySQL 中意向锁的主要作用是用于支持行级锁与表级锁的并存&#xff0c;特别是在 InnoDB 存储引擎中。InnoDB 提供了行级锁&#xff0c;而在某些场景下&#xff0c;数据库系统仍需要对整张表加锁&#xff0c;例如 LOCK TABLES …...

31个省份农业科技水平(农业技术创新或农业科技专利数据)2010-2022年

一、测算方式&#xff1a;参考C刊《湖北大学学报(哲学社会科学版)》张金鑫&#xff08;2020&#xff09;老师的做法&#xff0c;采用农业( 农林牧渔业) 三类专利总和来衡量农业技术创新 二、资料范围&#xff1a;31个省份&#xff0c;403个观测值&#xff0c;已经整理成面板数…...

Python代码执行失败问题及解决方案

目录 一、Python代码执行失败的原因 二、常见的Python错误类型 1. 语法错误&#xff08;SyntaxError&#xff09; 2. 运行时错误&#xff08;RuntimeError&#xff09; 3. 类型错误&#xff08;TypeError&#xff09; 4. 导入错误&#xff08;ImportError&#xff09; 5…...

Java 遗传算法

遗传算法&#xff08;Genetic Algorithm, GA&#xff09;是一种基于自然选择和遗传学原理的优化算法&#xff0c;用于求解复杂的搜索和优化问题。在Java中实现遗传算法通常包括以下几个步骤&#xff1a; 初始化种群&#xff1a;生成一组随机解作为初始种群。适应度评估&#x…...

C++ (一) 基础语法

基础语法&#xff1a;C的开胃小菜 欢迎来到C的世界&#xff0c;这里是编程的盛宴&#xff0c;也是逻辑的迷宫。别担心&#xff0c;我们不会一开始就让你啃硬骨头&#xff0c;而是从基础语法开始&#xff0c;让你慢慢品尝编程的美味。准备好了吗&#xff1f;让我们开始这场编程…...

Qt/C++路径轨迹回放/回放每个点信号/回放结束信号/拿到移动的坐标点经纬度

一、前言说明 在使用百度地图的路书功能中&#xff0c;并没有提供移动的信号以及移动结束的信号&#xff0c;但是很多时候都期望拿到移动的哪里了以及移动结束的信号&#xff0c;以便做出对应的处理&#xff0c;比如结束后需要触发一些对应的操作。经过搜索发现很多人都有这个…...

C 语言介绍及操作案例

C 语言是一种广泛使用的通用编程语言,具有高效、灵活和可移植性强等特点。 一、C 语言的基本特点 简洁高效 C 语言语法简洁,表达能力强。它提供了丰富的数据类型和运算符,可以方便地进行各种计算和操作。C 语言的代码执行效率高,能够直接访问硬件资源,适用于对性能要求较…...

Ivanti云服务被攻击事件深度解析:安全策略构建与未来反思

攻击事件背景 近期&#xff0c;威胁情报和研究机构Fortinet FortiGuard Labs发布了一份关于针对IT解决方案提供商Ivanti云服务设备&#xff08;Ivanti Cloud Services Appliance&#xff0c;CSA&#xff09;的复杂网络攻击的详细分析。 该攻击被怀疑是由国家级对手发起&#xf…...

如何做出正确选择编程语言:关于Delphi 与 C# 编程语言的优缺点对比

概述 为您的项目选择正确的技术可能是一项相当棘手的任务&#xff0c;尤其是当您以前从未需要做出这样的选择时。如今可用的选项范围非常广泛。虽然一些编程语言和工具有着相当悠久的历史&#xff0c;但其他一些则是刚刚开始赢得开发人员青睐的新手。 在这篇博文中&#xff0…...

XCTF-web-easyupload

试了试php&#xff0c;php7&#xff0c;pht&#xff0c;phtml等&#xff0c;都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接&#xff0c;得到flag...

ES6从入门到精通:前言

ES6简介 ES6&#xff08;ECMAScript 2015&#xff09;是JavaScript语言的重大更新&#xff0c;引入了许多新特性&#xff0c;包括语法糖、新数据类型、模块化支持等&#xff0c;显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var&#xf…...

深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法

深入浅出&#xff1a;JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中&#xff0c;随机数的生成看似简单&#xff0c;却隐藏着许多玄机。无论是生成密码、加密密钥&#xff0c;还是创建安全令牌&#xff0c;随机数的质量直接关系到系统的安全性。Jav…...

无法与IP建立连接,未能下载VSCode服务器

如题&#xff0c;在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈&#xff0c;发现是VSCode版本自动更新惹的祸&#xff01;&#xff01;&#xff01; 在VSCode的帮助->关于这里发现前几天VSCode自动更新了&#xff0c;我的版本号变成了1.100.3 才导致了远程连接出…...

江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命

在华东塑料包装行业面临限塑令深度调整的背景下&#xff0c;江苏艾立泰以一场跨国资源接力的创新实践&#xff0c;重新定义了绿色供应链的边界。 跨国回收网络&#xff1a;废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点&#xff0c;将海外废弃包装箱通过标准…...

【算法训练营Day07】字符串part1

文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接&#xff1a;344. 反转字符串 双指针法&#xff0c;两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...

C# 类和继承(抽象类)

抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...

uniapp中使用aixos 报错

问题&#xff1a; 在uniapp中使用aixos&#xff0c;运行后报如下错误&#xff1a; AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...

云原生玩法三问:构建自定义开发环境

云原生玩法三问&#xff1a;构建自定义开发环境 引言 临时运维一个古董项目&#xff0c;无文档&#xff0c;无环境&#xff0c;无交接人&#xff0c;俗称三无。 运行设备的环境老&#xff0c;本地环境版本高&#xff0c;ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...

【C++进阶篇】智能指针

C内存管理终极指南&#xff1a;智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...