【算法】二分查找算法——leetcode二分查找、搜索插入位置

文章目录

  • 二分查找
    • 704. 二分查找
    • 35. 搜索插入位置

二分查找

  二分查找算法是一种在有序数组中查找特定元素的搜索算法。算法的工作原理是,通过比较数组中间元素和目标值,如果目标值等于中间元素,那么查找结束。如果目标值小于或大于中间元素,则在数组的前半部分或后半部分进行查找。此过程将一直持续到找到目标值,或者搜索范围为空。

  需要注意的是,二分查找算法只适用于已排序的数组。如果给定的数组是无序的,那么在进行二分查找之前,需要先对数组进行排序。

  以下是一个朴素二分查找算法的步骤:

  (1)选择数组的中间元素。

  (2)如果中间元素正好是要查找的元素,则搜索过程结束。

  (3)如果要查找的元素大于中间元素,则在数组的后半部分进行搜索。

  (4)如果要查找的元素小于中间元素,则在数组的前半部分进行搜索。

             

在这里插入图片描述

704. 二分查找

二分查找

(1)二分查找

  算法思路:(当 right = nums.size()-1 时)

  我们定义 left , right 指针,分别指向数组的左右区间。之后找到待查找区间的中间点 middle ,找到之后分三种情况讨论:

(1)nums[middle] == target 说明正好找到,返回 mid 的值;

(2)nums[middle] > target 说明 [middle, right] 这段区间都是大于 target 的, 因此舍去右边区间,在左边 [left, middle -1] 的区间继续查找,即让 right = middle - 1 ,然后重复 2 过程;

(3)nums[middle] < target 说明 [left, middle] 这段区间的值都是小于 target 的, 因此舍去左边区间,在右边 [middle + 1, right] 区间继续查找,即让 left = middle + 1 ,然后重复 2 过程;

  当 left 与 right 错开时,说明整个区间都没有这个数,返回 -1。

             

  算法实现过程:(当 right = nums.size()-1 时)

  首先,它初始化两个指针,‘left’和’right’,分别指向数组的开始和结束。 然后,它进入一个循环,在循环中,它找到数组中间的元素(‘middle’),并根据这个中间元素和目标值的比较结果来更新搜索范围。

  如果中间元素等于目标值,那么函数就返回中间元素的索引。

  如果中间元素大于目标值,那么目标值必然在数组的左半部分, 所以它将’right’指针移动到’middle - 1’,缩小搜索范围为左半部分。

  否则,目标值必然在数组的右半部分, 所以它将’left’指针移动到’middle + 1’,缩小搜索范围为右半部分。

  如果在数组中没有找到目标值,那么函数返回-1。

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

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

             

当然right也可以等于nums.size()

  和上面的代码实现基本类似,只是有些条件需要改变。
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

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

在这里插入图片描述

时间复杂度:O(logn)

             

35. 搜索插入位置

搜索插入位置

在这里插入图片描述
             

(1)二分查找

  算法思路:

  (1)设插入位置的坐标为 index , 根据插入位置的特点可以知道:
  [left, index - 1] 内的所有元素均是小于 target 的;
  [index, right] 内的所有元素均是大于等于 target 的。

  (2)设 left 为本轮查询的左边界, right 为本轮查询的右边界。 根据 mid 位置元素的信息,分析下⼀轮查询的区间:
  当 nums[mid] >= target 时,说明 mid 落在了 [index, right] 区间上, mid 左边包括 mid 本身,可能是最终结果,所以我们接下来查找的区间在 [left, mid] 上。因此,更新 right 到 mid 位置,继续查找。
  当 nums[mid] < target 时,说明 mid 落在了 [left, index - 1] 区间上, mid 右边但不包括 mid 本⾝,可能是最终结果,所以我们接下来查找的区间在 [mid +1, right] 上。因此,更新 left 到 mid + 1 的位置,继续查找。

  (3)直到我们的查找区间的长度变为 1 ,也就是 left == right 的时候, left 或者right 所在的位置就是我们要找的结果。

             

  算法实现:

  (1)初始化两个指针,left和right,分别指向数组的开始和结束。

  (2)进入一个while循环,只要left小于right,循环就会继续。 在循环中,首先找到数组中间的元素(mid)。

  (3)如果中间元素小于目标值,那么目标值必然在数组的右半部分,所以将left移动到mid+1,缩小搜索范围为右半部分。

  (4)否则,目标值必然在数组的左半部分或者就是中间元素本身,所以将right移动到mid,缩小搜索范围为左半部分或者就是中间元素。

  (5)当循环结束时,right指向的元素可能是目标值,也可能不是。如果这个元素小于目标值,说明目标值应该插入到数组的右侧,所以返回right+1;否则,返回right。

class Solution {
public:int searchInsert(vector<int>& nums, int target) {int left=0,right=nums.size()-1;while(left<right){int mid=(left+right)/2;if(nums[mid]<target)left=mid+1;elseright=mid;}if(nums[right]<target)//判断target是否大于nums中的最大值return right+1;return right;}
};

在这里插入图片描述

时间复杂度:O(logn)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/129398.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux驱动【day2】

mychrdev.c: #include <linux/init.h> #include <linux/module.h> #include <linux/fs.h> #include<linux/uaccess.h> #include<linux/io.h> #include"head.h" unsigned int major; // 保存主设备号 char kbuf[128]{0}; unsigned int…

产品波士顿矩阵

随着公司产品的增多&#xff0c;每个产品的生命周期节点各不相同&#xff0c;很多时候我们往往在产品结构、资源分配方面会产生各种问题&#xff0c;导致需要发展的产品得不到资源&#xff0c;消耗资源的产品却有无法增长&#xff0c;所谓不聚焦导致的问题其实是资源和发展错配…

ETCD详解

一、etcd概念 ETCD 是一个高可用的分布式键值key-value数据库&#xff0c;可用于服务发现。 ETCD 采用raft 一致性算法&#xff0c;基于 Go语言实现。 etcd作为一个高可用键值存储系统&#xff0c;天生就是为集群化而设计的。由于Raft算法在做决策时需要多数节点的投票&…

编程中的信号处理和系统 - 初学者指南

信号处理是工程和编程的一个重要领域。 基本上,它允许工程师和程序员改进数据,以便人们可以更有效地使用它。 例如,由于信号处理,电话中的大部分背景噪音都被消除了。这样,通话的另一端就只能听到您的声音。 其他例子有: 音频和音乐软件图像视频处理软件医学影像软件语…

Modelsim仿真问题解疑二:ERROR: [USF-ModelSim-70]

现象&#xff1a;在Vivado中已配置modelsim为仿真工具后&#xff0c;运行仿真&#xff0c;报错USF-ModelSim-70和ERROR: [Vivado 12-4473] 详细报错内容如下 ERROR: [USF-ModelSim-70] compile step failed with error(s) while executing C:/Users/ZYP_PC/Desktop/verilog_t…

JavaScript构造函数

1、构造函数&#xff1a; 是一个函数&#xff0c;是通过new运算符进行调用&#xff0c;生成一个特殊的对象并返回。 function 函数名([参数]){ this.属性名 ‘属性值’ ... this.属性名 function([参数]){ 函数体语句 } } 通常情况下&#xff0c;建议构造函数的首字母大写 …

ELK日志框架图总结

ELK日志框架图总结 本文目录 ELK日志框架图总结Elastic Stack介绍模式分层图beatselasticsearchkibana模式logstashelasticsearchkibana模式beatslogstashelasticsearchkibana模式beats缓存/消息队列logstashelasticsearchkibana模式elkspringboot Elastic Stack介绍 官网&…

无涯教程-JavaScript - MIRR函数

描述 MIRR函数针对一系列定期现金Stream返回修改后的内部收益率。 MIRR会同时考虑投资成本和现金再投资收到的利息。 语法 MIRR (values, finance_rate, reinvest_rate)争论 Argument描述Required/OptionalValues 包含数字的单元格的数组或引用。这些数字表示定期发生的一系…

数据结构与算法:练习与实践的重要性

文章目录 为什么练习与实践很重要&#xff1f;1. 熟练应用2. 问题解决能力3. 代码效率4. 面试准备 如何练习与实践&#xff1f;1. 在线评测平台2. 自主设计数据结构3. 解决不同类型的问题 持续学习与实践 &#x1f389;欢迎来到数据结构学习专栏~数据结构与算法&#xff1a;练习…

SQL注入 - 宽字节注入

文章目录 SQL注入 - 宽字节注入宽字节注入前置知识宽字节靶场实战判断是否存在SQL注入判断位数判显错位判库名判表名判列名 SQL注入 - 宽字节注入 靶场 sqli - labs less-32 宽字节注入主要是绕过魔术引号的&#xff0c;数据库解析中除了UTF-8编码外的所有编码如&#xff1a;G…

算法之双指针题型:

双指针例题小总结&#xff1a; 力扣27&#xff1a; 移除元素 力扣题目链接 双指针分为&#xff1a; 快慢双指针&#xff1a;同一个起点&#xff0c;同向出发 相向双指针&#xff1a;从两端出发&#xff0c;方向相反&#xff0c;终会相遇 经典的双指针&#xff08;快慢双指…

pytorch代码实现之SAConv卷积

SAConv卷积 SAConv卷积模块是一种精度更高、速度更快的“即插即用”卷积&#xff0c;目前很多方法被提出用于降低模型冗余、加速模型推理速度&#xff0c;然而这些方法往往关注于消除不重要的滤波器或构建高效计算单元&#xff0c;反而忽略了特征内部的模式冗余。 原文地址&am…

Linux查端口占用的几种方式

在Linux中&#xff0c;你可以使用以下几种方式来查看端口的占用情况。 一、使用netstat命令 #安装netstat yum -y install net-tools #检测端口占用 netstat -npl | grep 端口# 几种常规用法 netstat -ntlp //查看当前所有tcp端口 netstat -ntulp | grep 80 //查看所有80端…

java设计模式,简单工厂和抽象工厂有什么区别?

java设计模式&#xff0c;简单工厂和抽象工厂有什么区别&#xff1f; 简单工厂模式&#xff1a; 这个模式本身很简单而且使用在业务较简单的情况下。一般用于小项目或者具体产品很少扩展的情况&#xff08;这样工厂类才不用经常更改&#xff09;。 它由三种角色组成&#xf…

MySQL 8.0.34(x64)安装笔记

一、背景 从MySQL 5.6到5.7&#xff0c;再到8.0&#xff0c;版本的跳跃不可谓不大。安装、配置的差别也不可谓不大&#xff0c;特此备忘。 二、过程 &#xff08;1&#xff09;获取MySQL 8.0社区版&#xff08;MySQL Community Server&#xff09;   从 官网 字样 “MySQL …

卡尔曼滤波公式推导(总结)

假设 小车在t时刻的初始状态可以用Pt&#xff08;当前位置&#xff09;&#xff0c;Vt&#xff08;当前速度&#xff09;&#xff0c;Ut表示加速度&#xff1a; 预测&#xff1a; 利用上一个时刻的旧状态和系统的动量模型&#xff08;如加速度&#xff0c;速度等&#xff09;…

扫码支付系统_分账收款系统_设计开发OctShop

在当今&#xff0c;移动支付在我们生活中已经是不可或缺的东西&#xff0c;以微信和支付宝为代表的扫码支付系统正在各种线下消费场景中使用&#xff0c;给我们日常的生活购物消费带来了不少的便利。第一些第三方的扫码支付系统更是集合了各种支付渠道&#xff0c;买家或消费者…

yolov5添加ECA注意力机制

ECA注意力机制简介 论文题目&#xff1a;ECA-Net: Efficient Channel Attention for Deep Convolutional Neural Networks 论文地址&#xff1a;here 基本原理 &#x1f438; ECANet的核心思想是提出了一种不降维的局部跨通道交互策略&#xff0c;有效避免了降维对于通道注意…

一个CVE漏洞预警知识库

CVE 0x01 免责声明 本仓库所涉及的技术、思路和工具仅供安全技术研究&#xff0c;任何人不得将其用于非授权渗透测试&#xff0c;不得将其用于非法用途和盈利&#xff0c;否则后果自行承担。 无exp/poc&#xff0c;部分包含修复方案 0x02 项目导航 2022.12 CVE-2022-3328&a…

Purple Pi OH(Debian/Ubuntu)使用python控制gpio

本文分享的是Purple Pi OH开源主板搭载Debian/Ubuntu系统如何使用python控制gpio。 Purple Pi OH作为一款兼容树莓派的开源主板&#xff0c;采用瑞芯微RK3566 (Cortex-A55) 四核64位超强CPU,主频最高达1.8 GHz,算力高达1Tops&#xff0c;支持INT8/INT16&#xff0c;支持Tensor…