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

news2024/11/24 19:09:44

1.朴素二分查找

.二分查找

二分查找思路:
1.left=0,right=nums.size()-1(最后一个元素下标),取中间元素下标 mid=left+(right-left)/2 (防溢出)

2.nums[mid]>target ,说明mid右边的元素都大于target,就不用再从mid右边查找。right=mid-1

3.nums[mid]<target ,说明mid左边的元素都小于target,就不用再从mid左边查找。

left=mid+1

4.nums[mid]==tartget,找到目标值返回。

5.循环条件 left<=right,当left==right时,意味着只剩最后一个元素,有可能是目标值。

不断循环直到找到目标结果,或者left>right不满足循环条件。

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

2.查找区间左端点/右端点

在排序数组中查找元素的第一个和最后一个位置

这道题如果用朴素二分查找,虽然可以找到target==8的元素,但不一定就是目标值。

找到目标值再向左 向又查找不行吗?可以,但效率会降低。我们有其它方法可以更好的解决。

1.查找区间左端点

该方法对于朴素二分法不同的是,朴素二分法把区间分为3份,>target ==target <target。

查找区间左端点把区间分为2份,<target >=target(默认非递减)。

eg1.[5 7 7]  [8 8 10] 而目标值就在右区间的最左边。

1.如果mid落在左区间,mid指向的元素肯定不是目标值,可以让left=mid+1

2.如果mid落在右区间,mid指向的元素有可能是目标值,所以让right=mid 如果-1可能会跳过目标值。

所以right只会在右区间移动,而left最远只会到右区间的最左边。所以当left==right就可以求出结果。

3.循环条件为left<right,不能是left<=right,如果等于会一直循环,left==right

mid=(left+right)/2 mid值不变,还是在右区间,right=mid right值也不变。

4.mid的取值,mid=left+(right-left) 还是向上取整 mid=left+(right-left+1)?有什么区别?

如果只剩两个数[5 7 7]  [8 8 10] 的7 8。left指向7 right指向8,mid=left+(right-left+1) mid=1

此时mid指向8,落在右区间,right=mid。再取mid还是指向8,就会无限循环。

所以mid=left+(right-left) mid=0取靠左边的值,指向7,落在左区间,left=mid+1。此时left==right循环结束。

下面举2种极端情况

1.数组值全>target 只有右区间,right不断移动 left==0不动.left==right指向下标0

2.数组值全<arget 只有左区间,left不断移动 right==nums.szie()-1不动.left==right指向最后一个元素(因为mid=left+(right-left) mid=0取靠左边的值 不会出现mid==right left=mid+1越界的情况

 2.查找区间右端点

和查找左端点本质一样,但细节不同。

查找区间右端点把区间分为2份,<=target >target(默认非递减)。

eg1.[5 7 7 8 8] [ 10 ] 而目标值就在左区间的最右边。

1.如果mid落在右区间,mid指向的元素肯定不是目标值,可以让right=mid-1 

2.如果mid落在左区间,mid指向的元素可能是目标值,所以让left=mid 

所以left只会在左区间移动,而right最远只会到左区间的最右边。所以当left==right就可以求出结果。

3.循环条件为left<right,不能是left<=right,如果等于会一直循环,left==right

mid=(left+right)/2 mid值不变,还是在左区间,left=mid left值也不变。

4.mid的取值,mid=left+(right-left) 还是向上取整 mid=left+(right-left+1)?有什么区别?

如果只剩两个数[5 7 7 8 8 ][10] 的8 10。left指向8 right指向10,mid=left+(right-left) mid=0取靠左边的值 此时mid指向8,落在左区间,left=mid。再取mid还是指向8,就会无限循环。

所以mid=left+(right-left+1) mid=1取靠右边的值,指向10,落在右区间,right=mid-1。此时left==right循环结束。

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        int le=-1,ri=-1;
        int left=0,right=nums.size()-1,mid=0;
        //处理边界情况
        if(nums.empty()) return {-1,-1};
        //取左端点下标
        while(left<right)
        {
            mid=left+(right-left)/2;//取靠左边的值
            if(nums[mid]<target)
              left=mid+1;
            else
              right=mid;
        }
        le=left;
        left=0,right=nums.size()-1;
        //取右端点下标
        while(left<right)
        {
            mid=left+(right-left+1)/2;//取靠右边的值
            if(nums[mid]<=target)
              left=mid;
            else
              right=mid-1;
        }
        ri=left;
        if(nums[left]==target) return {le,ri};
        else return {-1,-1}; //没找到的情况
    }
};

1.如果目标值是左端点,就把它套在右区间[5 7 7]  [8 8 10],让左边的+1来找,mid就要取靠左的值

2.如果目标值是右端点,就把它套在左区间[5 7 7 8 8 ][10],让右边的-1来找,mid就要取靠右的值

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

软考:缓存和数据库数据一致性问题

参考&#xff1a;CSDN博客&#xff0c;8种方案 前言 为什么要一致 如果数据不一致&#xff0c;那么业务应用从缓存中读取的数据就不是最新的数据&#xff0c;这会导致严重的错误 数据一致性是什么 缓存中有数据&#xff0c;那么&#xff0c;缓存的数据需要和数据库中的值相同 …

vue图片加载失败的图片

1.vue图片加载失败的图片 这个问题发生在测试环境和开发本地&#xff0c;线上环境是可以的&#xff0c;测试环境估计被第三方屏蔽了 2.图片有&#xff0c;却加载不出来 <template v-slot:imageUrlsSlots"{ row }"><div class"flexRow rowCenter"&…

重生之“我打数据结构,真的假的?”--3.栈和队列(无习题)

栈和队列 C语言中的栈和队列总结 在C语言中&#xff0c;**栈&#xff08;Stack&#xff09;和队列&#xff08;Queue&#xff09;**是两种非常重要的数据结构。它们广泛用于各种应用中&#xff0c;比如内存管理、任务调度、表达式求值等。本文将对这两种数据结构进行详细的介…

element ui中el-image组件查看图片的坑

比如说上传组件使用el-image-viewer组件去看&#xff0c;如果用错了&#xff0c;你会发现&#xff0c;你每次只能看一张图片 <template><div><el-upload action"#" list-type"picture-card" :auto-upload"false" :file-list"…

LTSC版本没有微软应用商店怎么办?一招装上

前言 这几天小白在办公电脑上安装了Windows 11 24H2 LTSC版本&#xff0c;哦豁&#xff0c;界面真的清爽。默认桌面上只有一个垃圾桶和EDGE浏览器&#xff0c;就再也没有其他图标了。 &#xff08;吐槽1️⃣&#xff1a;原版系统镜像开机之后不都是这样的吗&#xff1f;这也能…

Rust初踩坑

一、下载 到官网https://www.rust-lang.org/zh-CN/tools/install下载你需要的版本 二、安装 执行rustup-init 文件&#xff0c;选择1 按提示直到安装完成 可以通过以下命令测试&#xff1a; rustc -V # 注意的大写的 V cargo -V # 注意的大写的 V三、在VScode中…

GFF: Gated Fully Fusion for Semantic Segmentation门控融合语义分割-论文阅读笔记

摘要&#xff1a; 语义分割通过对每个像素密集预测其类别&#xff0c;生成对场景的全面理解。深度卷积神经网络的高级特征已经在语义分割任务中证明了它们的有效性&#xff0c;然而高级特征的粗分辨率经常导致对小/薄物体的结果不佳&#xff0c;而这些物体的细节信息非常重要。…

如何在算家云搭建GPT-SOVITS(语音转换)

一、模型介绍 GPT-SOVITS是一款强大的小样本语音转换和文本转语音 WebUI工具。它集成了声音伴奏分离、自动训练集分割、中文ASR和文本标注等辅助工具。 具有以下特征&#xff1a; 零样本 TTS&#xff1a; 输入 5 秒的声音样本并体验即时文本到语音的转换。少量样本 TTS&…

Rust的move关键字在线程中的使用

为什么使用 move&#xff1f; 在 Rust 中&#xff0c;move 关键字主要用于闭包。当我们在一个线程中创建一个闭包并将其传递给另一个线程时&#xff0c;如果闭包中使用了某些变量&#xff0c;就需要决定这些变量的所有权归属。 不使用 move&#xff1a; 默认情况下&#xff0…

python实战项目42:themoviedb电影网站信息

python爬取themoviedb电影网站信息 一、寻找数据接口二、解析主页数据,获取详情页url三、向详情页url发送请求、获取并解析数据四、完整代码一、寻找数据接口 打开网站首页,F12打开开发者工具,刷新页面。 向下滑动页面,点击页面上的“Load More”图标。 寻找到数据接口,…

【网络原理】TCP/IP五层网络模型之网络层-----IP协议详解,建议收藏!!

&#x1f490;个人主页&#xff1a;初晴~ &#x1f4da;相关专栏&#xff1a;计算机网络那些事 前几篇文章中我们深入研究了TCP协议&#xff0c;因为TCP协议在我们日常开发中的使用频率非常高。而相比之下&#xff0c;IP协议与我们普通程序员关系就没那么近了。一般是专门开发…

2024年妈杯MathorCup大数据竞赛A题超详细解题思路

2024年妈杯大数据竞赛初赛整体难度约为0.6个国赛。A题为台风中心路径相关问题&#xff0c;为评价预测问题&#xff1b;B题为库存和销量的预测优化问题。B题难度稍大于A题&#xff0c;可以根据自己队伍情况进行选择。26日早六点之前发布AB两题相关解题代码论文。 下面为大家带来…

创建型模式-----建造者模式

目录 背景&#xff1a; 构建模式UML 代码示例 房子成品&#xff1a; 构建器抽象&#xff1a; 具体构建器&#xff1a; 建筑师&#xff1a; 测试部…

配置nginx服务通过ip访问多网站

1.关闭防火墙 [rootlocalhost wzj]# systemctl stop firewalld [rootlocalhost wzj]# sstenforce 0 bash: sstenforce: command not found... [rootlocalhost wzj]# setenforce 0 2&#xff0c;挂mnt [rootlocalhost wzj]# mount/dev/sr0/mnt bash: mount/dev/sr0/mnt: No suc…

C++20中头文件ranges的使用

<ranges>是C20中新增加的头文件&#xff0c;提供了一组与范围(ranges)相关的功能&#xff0c;此头文件是ranges库的一部分。包括&#xff1a; 1.concepts: (1).std::ranges::range:指定类型为range&#xff0c;即它提供开始迭代器和结束标记(it provides a begin iterato…

【WPF】中Dispatcher的DispatcherPriority参数使用

在 WPF 中&#xff0c;DispatcherPriority 参数用于指定通过 Dispatcher 调度的操作的执行优先级。加入 DispatcherPriority 参数的情况通常取决于你希望操作何时以及如何被执行。 1.Dispatcher的DispatcherPriority参数使用 以下是几种情况和示例说明&#xff1a; 1.1 需要…

量子纠错--shor‘s 码

定理1 (量子纠错的条件) C是一组量子编码&#xff0c;P是映射到C上的投影算子。假设是一个算子元素描述的量子操作&#xff0c;那么基于量子编码C&#xff0c;存在一个能对抗描述的噪声的纠错操作R的充要条件是 对某个复元素厄米矩阵成立。 将算子元素称为导致的错误。如果这样…

数字 图像处理算法的形式

一 基本功能形式 按图像处理的输出形式&#xff0c;图像处理的基本功能可分为三种形式。 1&#xff09;单幅图像 单幅图像 2&#xff09;多幅图像 单幅图像 3&#xff09;单&#xff08;或多&#xff09;幅图像 数字或符号等 二 几种具体算法形式 1.局部处理邻域对于任一…

第二单元历年真题整理

1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 参考答案 1. A 2. A 3. A 4. D 5. D 6. D 解析&#xff1a; 栈和队列是两个不一样的结构&#xff0c;不能放在一起表示 7. B 8. C 解析&#xff1a; S --> A0 | B1 --> (S1 | 1) 0 | (S0 | 0)1 --> S10 | 10 | S…

Java程序员如何获得高并发经验?

高并发编程 提到并发编程很多人就会头疼了&#xff1b;首先就是一些基础概念&#xff1a;并发&#xff0c;并行&#xff0c;同步&#xff0c;异步&#xff0c;临界区&#xff0c;阻塞&#xff0c;非阻塞还有各种锁全都砸你脸上&#xff0c;随之而来的就是要保证程序运行时关键…