二分查找——34. 在排序数组中查找元素的第一个和最后一个位置

在这里插入图片描述

文章目录

    • 1. 题目
    • 2. 算法原理
      • 2.1 暴力解法
      • 2.2 二分查找
        • 左端点查找
        • 右端点查找
    • 3. 代码实现
    • 4. 二分模板

1. 题目

题目链接:34. 在排序数组中查找元素的第一个和最后一个位置 - 力扣(LeetCode)

给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。

如果数组中不存在目标值 target,返回 [-1, -1]

你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。

示例 1:

输入:nums = [5,7,7,8,8,10], target = 8
输出:[3,4]

示例 2:

输入:nums = [5,7,7,8,8,10], target = 6
输出:[-1,-1]

示例 3:

输入:nums = [], target = 0
输出:[-1,-1]

提示:

  • 0 <= nums.length <= 105
  • -109 <= nums[i] <= 109
  • nums 是一个非递减数组
  • -109 <= target <= 109

2. 算法原理

2.1 暴力解法

这里暴力解法也比较简单,直接遍历整个数组,记录第一次出现的位置和最后一次出现的位置,时间复杂度为O(N),这里就不示例了。

2.2 二分查找

这里是不能够直接二分的,直接二分我们还需要从中间再往两边搜索,如果该数组里面的值全是目标值,效率就会降为O(N)。

image-20231120204339458

这里还是利用二段性,我们可分开查找左右端点,分两种情况即可:

左端点查找

这里我们的判断条件是:nums[midi] < targetnums[midi] >= target

image-20231120210034869

midi落在左区间的的时候,肯定是没有我们要寻找的值的,我们让left = midi+1即可

midi落在右区间的时候,这个区域里面是有可能有我们的target,不能让right = midi - 1,这样会导致错失我们的target,所以直接让right = midi即可

细节处理

  • 循环条件:left < right
    这里一共就三种情况有目标值、全是大于目标值、全是小于目标值

    1. 有结果:left一直在不符合条件的区间移动;right一直在符合条件的区间移动,且不会超出这个区间

      letf要执行,每次都是执行的midi+1,所以当left跳出去的时候,正好是在目标值处

      所以left == right时,就是最终结果,无需判断
      image-20231120211821603

    2. 全是大于target:在次情况下,左区间的条件一直都不会命中,而right,则一直在向left这边移动,最后相遇的时候,我们只需判断相遇处是不是target

    3. 全是小于target:这个情况就和上面这个一样

    如果我们在left == right的时候判断了,那么就会进入死循环,无限命中右区间条件

  • 求中点:midi = left + (right - left)/2
    我们求中点的时候采用left+(right-left)/2这里是防止溢出,这种与left+(right-left+1)/2的区别就是当数组为偶数的时候,前者求的是靠左位置,而后者是靠右位置
    image-20231120213935757

    这个在普通二分是没什么影响的,可是在我们求端点的时候,进行最后一次操作:
    image-20231120214307392

    采用②求中点时,命中右区间的条件,则会陷入死循环

右端点查找

查找右端点和查找左端点思想一致

image-20231120214931330

这个求中点的方式就采用left+(right-left+1)/2靠右位置

3. 代码实现

class Solution
{
public:
    vector<int> searchRange(vector<int>& nums, int target)
    {
        //检查空数组
        if(nums.size() == 0)    return {-1,-1};

        int left = 0;
        int right = nums.size()-1;
        int begin = left;
        //查找左端点
        while(left < right)
        {
            int midi = left+(right-left)/2;
            if(nums[midi]<target)
            {
                left = midi+1;
            }
            else    right = midi;
        }
        //判断是否有结果
        if(nums[left] != target)    return {-1,-1};
        else    begin = left;   //记录左端点

        //查找右端点
        //left = 0;   //可不用重置
        right = nums.size()-1;
        while(left<right)
        {
            int midi = left+(right-left+1)/2;
            if(nums[midi]<=target)
            {
                left = midi;
            }
            else    right = midi-1;
        }
        return {begin,right};
    }
};

4. 二分模板

查找区间左端点:

while(left<right)
{
    int mid = left + (right -left)/2;
    if(...)
    {
        left = mid + 1}
    else
    {
        right = mid;
    }
}

查找区间右端点:

while(left<right)
{
    int mid = left + (right -left+1)/2;
    if(...)
    {
        left = mid;
    }
    else
    {
        right = mid - 1;
    }
}

当下面出现减肥的时候,上面就用加一

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

python实战—核心基础2(数字大小写转换) lv1

目录 一、核心代码解释 二、代码 三、运行截图 一、核心代码解释 1、range函数 函数语法&#xff1a;range(start, stop[, step]) 参数说明&#xff1a; start: 计数从 start 开始。默认是从 0 开始。例如range&#xff08;5&#xff09;等价于range&#xff08;0&#x…

11.15 监控目录文件变化

监视对指定目录的更改&#xff0c;并将有关更改的信息打印到控制台&#xff0c;该功能的实现不仅可以在内核层&#xff0c;在应用层同样可以。程序中使用ReadDirectoryChangesW函数来监视目录中的更改&#xff0c;并使用FILE_NOTIFY_INFORMATION结构来获取有关更改的信息。 Re…

【Java】线程状态

1、线程状态 初始-NEW: Thread : 对象已经创建&#xff0c;但start 方法还没调用. 终止-TERMINATED: Thread 对象还在,内核中的线程已经没了 运行-RUNNABLE: 就绪状态(线程已经在 cpu 上执行了/线程正在排队等待上 cpu 执行) 超时等待-TIMED WAITING: 阻塞.由于 sleep 这种固定…

从暗黑3D火炬之光技能系统说到-Laya非入门教学一~资源管理

我不知道那些喷Laya没有浏览器&#xff0c;嘲笑别人编辑器做不好&#xff0c;是什么水平&#xff1f; 首先目前国内除了WPS和飞书&#xff0c;就没有第三家公司能把编辑器做好。 要是一般的游戏开发者&#xff0c;如我&#xff0c;有一点点引擎代码&#xff08;某项目&#x…

时间序列预测实战(十七)PyTorch实现LSTM-GRU模型长期预测并可视化结果(附代码+数据集+详细讲解)

一、本文介绍 本文给大家带来的实战内容是利用PyTorch实现LSTM-GRU模型&#xff0c;LSTM和GRU都分别是RNN中最常用Cell之一&#xff0c;也都是时间序列预测中最常见的结构单元之一&#xff0c;本文的内容将会从实战的角度带你分析LSTM和GRU的机制和效果&#xff0c;同时如果你…

铝合金钻孔铣削去毛刺加工之高速电主轴解决方案

铝合金是一种轻质、高强度的材料&#xff0c;其出色的机械性能和良好的导电性、导热性使其在工业领域广受青睐特别是在航空、航天和汽车制造中&#xff0c;铝合金的身影更是随处可见。在铝合金加工过程中&#xff0c;高速电主轴可精准而高效地完成钻孔、铣削和去毛刺等任务&…

贪吃蛇游戏制作

首先在ecilsp里面创建两个包&#xff0c;启动和图形界面 在创建一个文件夹用来放图片 1.绘制图形界面 package com.snaketuxing.view;import java.awt.Color; import java.awt.EventQueue; import java.awt.Font; import java.awt.Frame; import java.awt.Graphics; import …

go语言的某些开发素质真低,完全就是缺教养。

我本人在github提过一个错误处理的提案&#xff0c;2023年11月20日微信公众号“脑子进煎鱼了” 记录了这个提案&#xff0c;在评论区有个微信名为&#xff1a;【hello哥已开始躺平】的微信用户一来就喷粪&#xff0c;这种人到底是欠打呢还是心理变态呢&#xff1f;对别人的提案…

docker更换国内源

docker更换国内源 1、编辑Docker配置文件 在终端中执行以下命令&#xff0c;编辑Docker配置文件&#xff1a; vi /etc/docker/daemon.json2、添加更新源 在打开的配置文件中&#xff0c;添加以下内容&#xff1a; {"registry-mirrors": ["https://hub-mirror…

yum 搭建仓库 http/ftp

目录 http ftp http 服务端 1. 下载 httpd 服务&#xff0c;记得将防火墙和安全终端全部关掉 2. 开启 httpd 服务 3. 临时挂载 客户端 1. 下载 httpd 服务&#xff0c;记得将防火墙和安全终端全部关掉 2. 开启 httpd 服务 3. 进入 /etc/yum.repos.d 4. 新建一个目录 mhy&…

【洛谷 P3743】kotori的设备 题解(二分答案+循环)

kotori的设备 题目背景 kotori 有 n n n 个可同时使用的设备。 题目描述 第 i i i 个设备每秒消耗 a i a_i ai​ 个单位能量。能量的使用是连续的&#xff0c;也就是说能量不是某时刻突然消耗的&#xff0c;而是匀速消耗。也就是说&#xff0c;对于任意实数&#xff0c;…

Vue3 源码解读系列(九)——依赖注入

依赖注入 依赖注入用于祖先组件向后代组件传递数据。 特点&#xff1a; 祖先组件不需要知道哪些后代组件在使用它提供的数据。 后代组件也不需要知道注入的数据来自哪里。 /*** provide 的实现*/ function provide(key, value) {let provides currentInstance.provides // 当…

【Linux】软连接和硬链接:创建、管理和解除链接的操作

文章目录 1. 软链接和硬链接简介2. Linux软链接使用方法3. Linux硬链接使用方法4. 总结 1. 软链接和硬链接简介 什么是软链接 软链接(Symbolic Link),也称为符号链接,是包含了源文件位置信息的特殊文件。它的作用是间接指向一个文件或目录。如果软链接的源文件被删除或移动了,软…

【论文阅读笔记】Deep learning for time series classification: a review

【论文阅读笔记】Deep learning for time series classification: a review 摘要 在这篇文章中&#xff0c;作者通过对TSC的最新DNN架构进行实证研究&#xff0c;探讨了深度学习算法在TSC中的当前最新性能。文章提供了对DNNs在TSC的统一分类体系下在各种时间序列领域中的最成功…

智慧化工园区信息化整体解决方案:PPT全53页,附下载

关键词&#xff1a;智慧化工园区建设方案&#xff0c;智慧化工园区建设规范&#xff0c;智慧化工园区建设指南 一、售智慧化工园区建设背景 随着工业化、信息化和数字化进程的加速&#xff0c;化工园区面临着越来越多的挑战&#xff0c;如安全生产、环境保护、能源消耗等问题…

[架构之路-247]:目标系统 - 设计方法 - 软件工程 - 结构化方法的基本思想、本质、特点以及在软件开发、在生活中的应用

目录 前言&#xff1a; 一、什么是非结构化方法 1.1 什么是非结构化方法 1.2 非结构化方法的适用场合 二、什么是结构化方法 1.1 结构化方法诞生的背景&#xff1a;软件规模发展&#xff1a;大规模、复杂系统的需要 1.2 概述 1.3 主要特点与核心思想 三、结构化方法在…

【C#二开业务冠邑】通过界面查看数据来源

前言 重构框架&#xff08;CS【C#】转BS【Java】&#xff09;时&#xff0c;突然发现公司的代码和数据库&#xff0c;有部分都没有写注释&#xff0c;嘎嘎&#xff0c;这不非常影响开发效率&#xff0c;于是乎&#xff0c;开始帮公司整理表结构和数据来源&#xff0c;也从而加…

ISP--Black Level Correction(黑电平矫正)

图像的每一个像素点都是由一个光电二极管控制的&#xff0c;由二极管将电信号&#xff0c;转换为数字信号。 那么&#xff0c;我们知道了&#xff0c;图像的像素值是与电信号强度相关的。但是&#xff0c;我们得知道&#xff0c;每一个光电二极管要想工作&#xff0c;都得有一定…

异步爬取+多线程+redis构建一个运转丝滑且免费http-ip代理池 (三)

内容提要: 如果说,爬取网页数据的时候,我们使用了异步,那么将数据放入redis里面,其实也需要进行异步;当然,如果使用多线程或者redis线程池技术也是可以的,但那会造成冗余; 因此,在测试完多线程redis搭配异步爬虫的时候,我发现效率直接在redis这里被无限拉低下来! 因此: 最终的r…

集合的自反关系和对称关系

集合的自反关系和对称关系 一&#xff1a;集合的自反关系1&#xff1a;原理&#xff1a;2&#xff1a;代码实现 二&#xff1a;对称关系1&#xff1a;原理&#xff1a;2&#xff1a;代码实现 三&#xff1a;总结 一&#xff1a;集合的自反关系 1&#xff1a;原理&#xff1a; …