算法综合篇专题三:二分法

news2025/1/11 4:25:28

bf1f8397c9d44264b5443464559ec884.jpeg

"寻一颗,未萌的渺小啊,随着青翠未来,升入辽阔云霄~" 


        现在你有一个"升序"数组,想让你在这个数组里完成查找数字n,在这个数组内的下标,你可以怎么做?这也许是不少友子们初遇二分问题的场景。你可以使用O(N)的时间复杂度,对该数组进行遍历,就像这样。

void FindNum(vector<int>& arr,int n)
{
    for(int i=0;i<arr.size();++i)
    {
        if(arr[i] == n) return i;
    }

    return -1;
}

        可是我们没有很好地利用到数组“有序”的特点,我们可以令数字为mid,那么借着有序的特点,可以将这个数组划分为两个区域,一边是小于mid的数,一边是大于mid的数。

void FindNum(vector<int>& arr,int n)
{
    int left = 0,right = arr.size()-1;

    while(left < right)
    {
        int mid = (left + right) / 2;
        if(arr[mid] < n) mid = left+1;
        else if(arr[mid] > m ) mid = right-1;
        else mid;
    }

    return -1;
}

        所以,按照这样的算法查找数组中的某个数,时间复杂度可以下降为O(logN),是一个特别大的提升,但使用这个算法的前前提的 “数组有序”。

——前言

1、二分查找

(1) 题目解析        f9a3f845bb3b42d1bb3e95c62a56779c.png

        这道题是最朴素的二分查找,同前言举的例子是一样的解题思路。

 

(2) 算法原理        

d0056ce375774868b00a1223b6035f8e.png

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int left = 0,right = nums.size()-1;
        // 当left==right时 当前元素是没有判断的
        // 因此这里需要再循环一次
        while(left <= right)
        {
            int mid = (left + right) / 2;
            if(nums[mid] > target){
                right = mid - 1;
            }
            else if(nums[mid] < target){
                left = mid + 1;
            }
            else return mid;
        }
        return -1;
    }
};

 


 

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

(1) 题目解析

31e02142d2b44dfeaf3533c880c94c9f.png

        根据数组"非递减顺序" 使用二分查找但朴素的二分查找只适用于查找一个数,所以这道题需要变形。


(2) 算法原理        bee3964a73014e459e951d3ce5b9467d.png

        查找区间右端点也是类似过程,只是需要注意细节处理:

e9b4f7b024fa484c93c2f16673eb3ef3.png

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        if(nums.empty()) return {-1,-1};
        int left = 0,right = nums.size()-1;
        vector<int> ret;
        // 找左端点
        while(left < right)
        {
            int mid = left + (right - left) / 2;
            if(nums[mid] < target){
                left = mid + 1;
            }
            else right = mid;
        }

        // 此时找到了左端点
        if(nums[left] != target) ret.push_back(-1);
        else ret.push_back(left);

        right = nums.size()-1;
        // 找右端点
        while(left < right)
        {
            int mid = left + (right - left + 1) /2;
            if(nums[mid] > target){
                right = mid - 1;
            }
            else left = mid;
        }
        if(nums[right] != target) ret.push_back(-1);
        else ret.push_back(right);
        return ret;
    }
};

 

3、搜索插⼊位置

(1) 题目解析

098af4949fcd4dc6821c14f9fc9b4cf8.png

        这道题可以使用左端点和右端点解决。

(2) 算法原理

722822375de941c0b5911f36e3a9dd84.png

左端点:

class Solution {
public:
    int searchInsert(vector<int>& nums, int target) {
        int left = 0,right = nums.size()-1;

        while(left < right)
        {
            int mid = left + (right - left) / 2;
            if(nums[mid] < target){
                left = mid + 1;
            }
            else right = mid;
        }

        // 可能该数不存在并且 > 当前数
        if(nums[left] < target) return left + 1;

        return left;
    }
};

右端点:

class Solution {
public:
    int searchInsert(vector<int>& nums, int target) {
        int left = 0,right = nums.size()-1;

        while(left < right)
        {
            int mid = left + (right - left + 1) / 2;
            if(nums[mid] > target){
                right = mid - 1;
            }
            else left = mid;
        }

        // 可能该数不存在并且 > 当前数
        if(nums[left] < target) return left + 1;

        return left;
    }
};

       


 

4. x 的平方根 

(1) 题目解析         0581cd0a3b844e88adeb4ba2a391fea6.png

 

(2) 算法原理        4e5a1bd44eae4391b2c0a77bbc8c048b.png

class Solution {
public:
    int mySqrt(int x) {
        if(x < 1) return 0;

        // 1~x
        int left = 1,right = x;
        while(left < right)
        {
            int mid = left + (right -left + 1) / 2;
            if(x < pow(mid,2))
            {
                right = mid - 1;
            }
            else left = mid;
        }
        return left;
    }
};

 

5、山脉数组的峰顶索引

(1) 题目解析

18e121e9c9254959ac3597d139e5efa2.png

        

(2) 算法原理

2f7134c2f8374765ad370b7344f64045.png

左端点:

class Solution {
public:
    int peakIndexInMountainArray(vector<int>& arr) {
        int left = 1,right = arr.size()-2;
        // [left,mid] [mid+1,right]
        while(left < right)
        {
            int mid = left + (right - left) / 2;
            // 左端点
            if(arr[mid] < arr[mid+1]){
                left = mid + 1;
            }
            else right = mid;
        }

        return right;
    }
};

 

右端点: 

class Solution {
public:
    int peakIndexInMountainArray(vector<int>& arr) {
        int left = 1,right = arr.size()-2;
        // [left,mid] [mid+1,right]
        while(left < right)
        {
            int mid = left + (right - left + 1) / 2;
            if(arr[mid] < arr[mid-1]){
                right = mid - 1;
            }
            else left = mid;
        }

        return left;
    }
};

6、寻找峰值 

(1) 题目解析

8c385c411aa546dab34c7ce0f00c9921.png

 

(2) 算法原理         15ba960526754aaeb048145681e8c555.png

class Solution {
public:
    int findPeakElement(vector<int>& nums) {
        if(nums.size() == 1) return 0;  
        int left = 0,right = nums.size() - 1;

        while(left < right)
        {
            // 左端点发
            int mid = left + (right - left) / 2;
            if(nums[mid] < nums[mid+1]){
                left = mid+1;
            }
            else right = mid;
        }
        
        return left;
    }
};

 


 

7、寻找旋转排序数组中的最小值

(1) 题目解析

83f6ac6ebff14fb8befd700ce9b59604.png
        如何找到本题的二段性是比较难点。

 

(2) 算法原理

        72dfd2a58eeb41398f0fe71bd26c26ae.png

class Solution {
public:
    int findMin(vector<int>& nums) {
        int left = 0,right = nums.size()-1;
        int x = nums[right]; //标记参照点
        while(left < right)
        {
            int mid = left + (right - left) / 2;
            if(nums[mid] > x){
                left = mid + 1;
            }
            else right = mid;
        }

        return nums[left];
    }
};

 


8、II. 0~n-1中缺失的数字

(1) 题目解析

c4ecbe361f0f4c85b4c343eb8dbfc8bf.png

 

(2) 算法原理        

class Solution {
public:
    int missingNumber(vector<int>& nums) {
        int left = 0,right = nums.size()-1;
        while(left < right)
        {
            int mid = left + (right-left) / 2;
            if(nums[mid] == mid) {
                left = mid + 1;
            }
            else right = mid;
        }
        // left为0时 特殊处理
        return  left == nums[left] ? left+1:left;
    }
};

本篇到此结束,感谢你的阅读。

祝你好运,向阳而生~

d6af3a90a3034d789408339d5d1ed37e.jpeg

 

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

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

相关文章

内存卡中毒了格式化能解决吗?这样清除病毒更有效

内存卡被广泛应用于手机、相机、MP3等数码产品&#xff0c;并且可以存储各种媒体文件&#xff0c;如视频、图片等。然而&#xff0c;在我们使用过程中&#xff0c;您是否因内存卡格式化而导致重要数据丢失感到困扰。对于“内存卡中毒了格式化能解决吗&#xff1f;“的疑惑&…

用于非线性多载波卫星信道的多输入多输出符号速率信号数字预失真器DPD(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

【LeetCode刷题篇零】一些基础算法知识和前置技能(下)

数组常用技巧 使用数组代替Map 使用另一个数组来统计每个数字出现的次数&#xff0c;数组的下标作为key, 数组的值作为value&#xff0c; 将数字作为数组的下标索引&#xff0c;数组里的值存储该数字出现的次数&#xff0c;原理有点类似桶排序中使用的计数数组。 比如这里如…

tensorboard可视化文件:events.out.tfevents.

跑了一个开源代码&#xff0c;跑完之后看到生成的文件夹里&#xff0c;出现了events.out.thevents.xxx的格式文件&#xff0c;比较好奇&#xff0c;进行了一番学习~   首先说明文件作用&#xff1a;用于tensorboard显示的可视化文件 使用方法 首先要安装tensorboard&#x…

mvn打包:依赖包和启动包分离

简述 依赖插件&#xff1a; maven-jar-plugin maven-assembly-plugin项目目录结构 assembly.xml <assembly xmlns"http://maven.apache.org/ASSEMBLY/2.1.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://…

zookeeper可视化界面zkui

获取zkui github地址&#xff1a;https://github.com/DeemOpen/zkui 可以使用客户端clone&#xff0c;我这里直接下载zip 解压 编译 如果将包下载到了linux&#xff0c;需要在linux中编译&#xff0c;我的linux没有maven&#xff0c;所以在window编译好&#xff0c;然后复制…

Win10显卡驱动安装失败怎么办

在更新Win10系统的过程中&#xff0c;显卡驱动也要跟着更新&#xff0c;近期有小伙伴反映在安装的过程中显示Win10显卡驱动安装失败&#xff0c;这是怎么回事&#xff0c;遇到这种问题应该怎么解决呢&#xff0c;下面小编就给大家详细介绍一下Win10显卡驱动安装失败的解决方法&…

一文说清mmap内存映射底层原理(以LCD中的Framebuffer为例)

一文说清mmap内存映射底层原理 【目录】 一、宏观解释内存映射 二、进程虚拟地址空间 三、虚拟内存区域描述符 四、内存映射的实现 五、mmap在Framebuffer中的应用 前几天的一场面试中&#xff0c;面试官问&#xff1a;为什么可以通过mmap直接操作LCD&#xff1f; 当…

上海亚商投顾:沪指放量反弹 医药、AI概念股集体走强

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 一.市场情绪 三大指数早间震荡反弹&#xff0c;午后集体拉升涨超1%&#xff0c;深成指一度涨超1.5%&#xff0c;随后涨幅略…

CSP 202104-1 灰度直方图

答题 就是记录每个数出现的次数&#xff0c;用C的map就行 #include<iostream> #include<map> using namespace std; int main(){map<int,int>h;int n,m,L,a;cin>>n>>m>>L;for(int i0;i<L;i){h[i]0;}while(n--){for(int i0;i<m;i){…

django configparser.NoSectionError: No section: ‘Samples

django configparser.NoSectionError: No section: Samples 背景&#xff1a;Windows下的Django项目&#xff0c;重新部署至Linux ubuntu20中。 samples_white_list eval(config.get(‘Samples’, ‘samples_white_list’)) File “/home/hhl/anaconda3/envs/django/lib/pytho…

Python + Jmeter 实现自动化性能压测

Step01: Python脚本开发 文件路径&#xff1a;D://wl//testproject//Fone-grpc//project1//test_client.py Python 脚本作用&#xff1a; 1.通过 grpc 调用底层 c 的接口&#xff0c;做数据库的数据插入与查询操作&#xff0c;然后将返回的结果进行拼接与输出。 2.代码里面…

optimizer和loss.backward()相关函数

optimizer.zero_grad() # 梯度清零(一定要先进行梯度清零&#xff0c;这样tensor里面的grad就不会累加) loss.backward()是用来求导的 optimizer.step()一般来说根据求来的导数进行梯度下降算法来更新参数 上面的顺序步骤不能变

Idea启动报错start failed闪退, RestfulToolkit-fix插件问题

前一天下班时还在正常使用的Idea&#xff0c;早上再次启动就报错闪退&#xff0c;报错信息非常的快的闪退也没有看清楚。做过的唯一更改就是前一天安装了 RestfulToolkit-fix 插件。 1、先查看报错的日志 在Idea安装路径的bin/ idea.bat文件中末尾处添加pause语句 保存后双击…

Python绘图系统16:动态更新tkinter组件

文章目录 前情提要源代码模式输入序列源码 Python绘图系统&#xff1a; &#x1f4c8;从0开始的3D绘图系统&#x1f4c9;一套3D坐标&#xff0c;多个函数&#x1f4ca;散点图、极坐标和子图自定义控件&#xff1a;极坐标&#x1f4c9;绘图风格&#x1f4c9;风格控件图表类型和…

软件产品(确认)有效性测试的作用和流程

一、基本概述 软件确认测试又称有效性测试&#xff0c;是在模拟的环境下&#xff0c;运用黑盒测试的方法&#xff0c;验证被测软件是否满足需求规格说明书列出的需求。任务是验证软件的功能和性能及其他特性是否与用户的要求一致。对软件的功能和性能要求在软件需求规格说明书…

数据清洗浅谈与理解

1.前言 今天和老同学交流了翻技术&#xff0c;准确的说是争执与讨论&#xff0c;谈到了数据清洗&#xff0c;特此记录一下对清洗的理解&#xff0c;分享与学习 2.数据清洗 下图出自小D课堂&#xff0c;本人也为小D课堂的忠实粉丝 类比现实去理解 ODS &#xff1a;未处理的…

【MapStruct】对象转换

【MapStruct】对象转换 【一】MapStruct带来的改变【二】MapStruct 入门【1】添加依赖【2】po类【3】dto类【4】创建转换接口【5】测试方法【6】运行效果【7】查看编译的class 【三】MapStruct优点分析【1】性能高【2】使用简单【3】代码独立【4】易于 debug 【四】MapStruct使…

【python 多线程】初体验+单线程下载器+多线程并行下载器+ 多进程下载器 以及线程和进程的切换成本比较

前置知识&#xff1a; ref&#xff1a;https://www.osgeo.cn/pillow/reference/ImageFile.html ref&#xff1a;https://blog.csdn.net/weixin_67510296/article/details/125207042 1.多线程初体验 主线程的id和进程的id是一个 查看进程pid下有多少个线程 ps -T -p pid(bas…

《追逐胜利:编程之路上的三子棋游戏实践》

文章目录 前言一、三子棋游戏规则二、步骤详解1.游戏菜单的实现2.棋盘的实现2.1 初始化棋盘2.2 打印棋盘 3.游戏逻辑实现3.1 玩家下棋3.2 电脑下棋 4.判断输赢4.1 win函数实现 5.完整代码 总结 前言 大家好&#xff01;我是艾老虎尤&#xff01;今天我很高兴来和大家分享我最近…