蓝桥杯 临时抱佛脚 之 二分答案法与相关题目

news2025/4/21 11:38:34

二分答案法(利用二分法查找区间的左右端点)

(1)估计 最终答案可能得范围 是什么

(2)分析 问题的答案 给定条件 之间的单调性,大部分时候只需要用到 自然智慧

(3)建立一个f函数, 当答案固定的情况下 ,判断 给定的条件是否达标

(4)在 最终答案可能的范围上不断二分搜索, 每次用f函数判断,直到二分结束,找到最合适的答案

(5)当题目要查找一个区间的左右端点时(符合的区间有多个值找最大或者最小),可以考虑一下这个方法能不能用

综上:

        核心点:分析单调性,建立f函数

光说不练,假把式!开练!!!!!

下面有一些相关题目

题目一:爱吃香蕉的珂珂

测试链接:875. 爱吃香蕉的珂珂 - 力扣(LeetCode)

题解:

1.        先看问题答案与对应条件的单调性,这道题中当吃香蕉的速度越大时,吃完所需要的时间就会越少,但这道题中要注意如果一小时内吃完一堆香蕉就会休息,等到下一个小时才会再次开始吃,如果一小时内没有吃完,那么下一个小时就会继续吃,吃完之后还是不会继续吃其他堆的香蕉,还是会休息。所以这个题会用到向上取整算法( 例如a/b向上取整,(a+b-1)/b

2.         分析要二分什么,问题要求返回h小时内吃掉所有香蕉的最小速度k(k为整数),那这道题就是二分速度,并且速度与时间也符合单调性,速度也快,时间越短。考虑二分速度的左右区间,左区间 速度最小为1 最大速度为数组中最大数据的大小,因为如果速度大于最大数据时,吃完之后也不会继续吃下一堆还是会休息,又有单调性所以最大数据的速度一定可以,但不会是答案。

3.        check函数,参数传速度,返回吃完所需要的时间,然后与给定的k作对比,不断的缩小范围直到二分结束,返回答案。

class Solution {
public:
    int minEatingSpeed(vector<int>& piles, int h) {
        //定区间
        int r = 0;
        //找到数组中最大的数据作为区间的右端点
        for(int i=0; i<piles.size();i++)
        {
            r = max(piles[i],r);
        }
        int ans = 0;
        //速度最小为1,左端点设置为1
        int l = 1;
        int mid =0;
        while(l<= r)
        {
            // 等价于mid = (l+r)/2  但有时会越界防止越界
            mid = l+((r-l)>>1); // 二分点靠左
            if(check(piles,mid) <= h){
                //达标
                //记录答案
                ans = mid;
                r = mid-1;
            }
            else{
                //不达标
                //不记录答案直接去右面二分
               l = mid+1;
            }
        }
        return ans;
    }
    //check函数检查是否符合要求
    long long check(vector<int>& piles, int mid)
    {
        //时间是向上取整 ,初始化long long类型数据,防止数据过大越界
        long long ans = 0;    // ans为时间
        int i = 0;
        int size = piles.size();
        while(size--)
        {
            // 时间是向上取整的
            ans += (piles[i++]-1)/mid + 1;
        }
        //返回mid速度,吃完所需时间
        return ans;
    }
};

题目二:分割数组的最大值

题目链接:410. 分割数组的最大值 - 力扣(LeetCode) (画匠问题)

题解:

1.        总结题意就是将数组分成规定的份数,然后返回分好的这些组中各自和的最大值的最小(就是组内的和最大的组的和使这个数即可能的小返回最小)

2        先看看这道题中最终答案,与给定条件之间是否存在单调性,最答案是各自总和的最大值,给定条件为划分成几份,当划分的分数越多,各自的总和就会越小,存在一定的单调性。

3.        思路就是写一个函数,传递的参数就是各自总和的最大值,然后返回满足在这个限制下,会将数组分成几份,然后与给定的k作对比,不断地缩小区间,直至二分结束

方法一:

        在后面check函数中处理特殊情况(容易忘记处理)

class Solution {
public:
    int splitArray(vector<int>& nums, int k) {
        //二分答案 将最大部分的累加和一直二分,写一个函数(每组数据都限制在这个累加和的范围内时是否符合要求小于等于k个)判断
        //非负整数可以为0

        //在前面可以将区间缩小到最小然后可以避免后面细节的判断防止出错
		//改法将左端点设置为最小0
        int l = 0;
        //二分区间的右端点,就是累计和的最大也就是将数组分成一份就是数组中所有元素的累加和 
        int r = 0;
        for(int i = 0; i<nums.size();i++)
        {
            r += nums[i];
        }
        //起始将mid设为0 
        int mid = 0;
        //ans来记录二分的答案,当答案满足记录下来继续二分 
        int ans = 0;
        //确定了二分的大致范围
        while(l<=r)
        {
        	//mid = (r+l)/2 下面这样写可以防止越界超过int的最大数值 
            mid = l+((r-l)>>1);
            //下面可以这样理解,返回值小于<=k,就是符合限制条件并且分的分数还比规定的小,那么一定有mid 
            if( check(nums,mid) <= k)
            {
                //mid都符合要求,右面的limit一定符合要求,所以去左面进行二分查找
                //先记录答案,然后去做左面看有没有最优解
                ans = mid;
                r = mid-1;
            }
            else
            {
            	//不符合要求,去右面找 
                l = mid +1;
            }
        }
        return ans;
    }
    //可以说用到了贪心算法,就是没个部分都是最优解,这样分的份数最小 
    int check(vector<int>& nums, int limit)
    {
        int sum = 0;
        int ret= 1; //代表最少分几份
        for(int i = 0 ;i<nums.size();i++)
        {
            //如果数组中有值超过了限制,这个限制不成立
            if(nums[i] > limit) return INT_MAX;

            if(sum + nums[i] <= limit)
            {
                //没有满 将数据吸纳进来
                sum += nums[i];
            }
            else{
                //当前sum结束了,现在sum的值为当前num[i]的值
                ret++;
                sum = nums[i];
            }
        }
        return ret;
    }
};

方法二:

        在前面划分左右区间时就将区间范围划分到最小,这样可以避免处理后面,数组中有大于限制情况。

class Solution {
public:
    int splitArray(vector<int>& nums, int k) {
        //二分答案 将最大部分的累加和一直二分,写一个函数(每组数据都限制在这个累加和的范围内时是否符合要求小于等于k个)判断
        //非负整数可以为0

        //在前面可以将区间缩小到最小然后可以避免后面细节的判断防止出错

        int l = 0;
        int r = 0;
        for(int i = 0; i<nums.size();i++)
        {
            r += nums[i];
            //区间的左值因为是数组划分完后的最大的最小值,所以一定大于等于数组中最大元素的值,将左端点设置为数组中最大的元素
            l = max(l,nums[i]);
        }
        int mid = 0;
        int ans = 0;
        //确定了二分的大致范围
        while(l<=r)
        {
            mid = l+((r-l)>>1);
            if( check(nums,mid) <= k)
            {
                //mid都符合要求,右面的limit一定符合要求,所以去左面进行二分查找
                //先记录答案,然后去做左面看有没有最优解
                ans = mid;
                r = mid-1;
            }
            else
            {
                l = mid +1;
            }
        }
        return ans;
    }
    int check(vector<int>& nums, int limit)
    {
        int sum = 0;
        int ret= 1; //代表最少分几份
        for(int i = 0 ;i<nums.size();i++)
        {
            if(sum + nums[i] <= limit)
            {
                //没有满 将数据吸纳进来
                sum += nums[i];
            }
            else{
                //当前sum结束了,现在sum的值为当前num[i]的值
                ret++;
                sum = nums[i];
            }
        }
        return ret;
    }
};

题目三:找出第K小的数对距离

题目链接:719. 找出第 K 小的数对距离 - 力扣(LeetCode)

题解:

1        题意数对距离就是两数之间的绝对值差值,题目要返回第k小的数对距离。

2        先看答案与给定条件之间的单调性关系,当两数的绝对值差值越大,那么这个K值也会越大,所以存在一定的单调性关系。

3        那么我们可以二分数对距离,根据题意找到最大最小的数对距离。

4         check函数我们可以传递mid位置的数对距离,然后返回mid位置为第几小的位置,与给定的k进行比较,直到二分结束。

class Solution {
public:
    int smallestDistancePair(vector<int>& nums, int k) {
    	//因为要找数据之间差值最大的两个数,并且该题排序与不排序不会影响最终结果 
        sort(nums.begin(),nums.end());
        //由于上面进行了排序所以右边界就是最大值与最小值的差值 
        int r = nums[nums.size() -1] - nums[0];
        //左边界就是数组中最小的差值,也就是数组之间相邻的两个数据最小的差值
        int l =r;
		for(int i = 1;i<nums.size()-1;i++)
		{
			l = min(r,nums[i]-nums[i-1]);
		} 
        int ans = 0;
        int mid = 0;
        while(l<=r)
        {
            mid = l+((r-l)>>1);
            //num为返回的第几小的元素,与k进行比较
            int num = check(nums,mid);
             
            if(num >= k)
            {
            	 //符合要求,将mid记录,这是mid可能已经为最终答案,记录以备候选,继续二分看是否还有最优解 
                ans = mid;
                r = mid -1;
            }
            else{
            	//mid不符合要求,缩小区间到mid的右面 
                l = mid +1;
            }
        }
        return ans;
    }
    //用来判断是不是与第k小的关系,也就是返回<=mid的数对数量
    int check(vector<int>& nums,int mid)
    {
    	//这道题应用到了滑动窗口的方法 
        int sum = 0;
        int r = -1, l = 0;
        for(l=0;l< nums.size();l++)
        {
            //从0开始存不能等于nums.size(),如果r+1 - l 的差值小于等于传进来的差值,就r++向后走,否则就停止 
                while(r < l || ((r+1)<nums.size() && nums[r+1] - nums[l] <= mid))
            {
                r++;
            }
            //因为l要加了,先将区间内符合条件的数据记录个数,L++,也就是l走之前记录l位置处的符合条件的个数 
            sum += r-l;
        }
        return sum;
    }
};

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

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

相关文章

【算法day22】两数相除——给你两个整数,被除数 dividend 和除数 divisor。将两数相除,要求 不使用 乘法、除法和取余运算。

29. 两数相除 给你两个整数&#xff0c;被除数 dividend 和除数 divisor。将两数相除&#xff0c;要求 不使用 乘法、除法和取余运算。 整数除法应该向零截断&#xff0c;也就是截去&#xff08;truncate&#xff09;其小数部分。例如&#xff0c;8.345 将被截断为 8 &#x…

关于服务器只能访问localhost:8111地址,局域网不能访问的问题

一、问题来源&#xff1a; 服务器是使用的阿里云的服务器&#xff0c;服务器端的8111端口没有设置任何别的限制&#xff0c;但是在阿里云服务器端并没有设置相应的tcp连接8111端口。 二、解决办法&#xff1a; 1、使用阿里云初始化好的端口&#xff1b;2、配置新的阿里云端口…

基于ADMM无穷范数检测算法的MIMO通信系统信号检测MATLAB仿真,对比ML,MMSE,ZF以及LAMA

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1 ADMM算法 4.2 最大似然ML检测算法 4.3 最小均方误差&#xff08;MMSE&#xff09;检测算法 4.4 迫零&#xff08;ZF&#xff09;检测算法 4.5 OCD_MMSE 检测算法 4.6 LAMA检测算法 …

Linux 配置时间服务器

一、同步阿里云服务器时间 服务端设置 1.检查chrony服务是否安装&#xff0c;设置chrony开机自启&#xff0c;查看chrony服务状态 [rootnode1-server ~]# rpm -q chrony # rpm -q 用于查看包是否安装 chrony-4.3-1.el9.x86_64 [rootnode1-server ~]# systemctl enable --n…

可视化web组态开发工具

BY组态是一款功能强大的基于Web的可视化组态编辑器&#xff0c;采用标准HTML5技术&#xff0c;基于B/S架构进行开发&#xff0c;支持WEB端呈现&#xff0c;支持在浏览器端完成便捷的人机交互&#xff0c;简单的拖拽即可完成可视化页面的设计。可快速构建和部署可扩展的SCADA、H…

C++笔记-模板初阶,string(上)

一.模板初阶 1.泛型编程 以往我们要交换不同类型的两个数据就要写不同类型的交换函数&#xff0c;这是使用函数重载虽然可以实现&#xff0c;但是有以下几个不好的地方&#xff1a; 1.重载的函数仅仅是类型不同&#xff0c;代码复用率比较低&#xff0c;只要有新类型出现时&a…

关于cmd中出现无法识别某某指令的问题

今天来解决以下这个比较常见的问题&#xff0c;安装各种软件都可能会发生&#xff0c;一般是安装时没勾选注册环境变量&#xff0c;导致cmd无法识别该指令。例如mysql&#xff0c;git等&#xff0c;一般初学者可能不太清楚。 解决这类问题最主要的是了解环境变量的概念&#x…

绿联NAS安装内网穿透实现无公网IP也能用手机平板远程访问经验分享

文章目录 前言1. 开启ssh服务2. ssh连接3. 安装cpolar内网穿透4. 配置绿联NAS公网地址 前言 大家好&#xff0c;今天给大家带来一个超级炫酷的技能——如何在绿联NAS上快速安装cpolar内网穿透工具。想象一下&#xff0c;即使没有公网IP&#xff0c;你也能随时随地远程访问自己…

d9-326

目录 一、添加逗号 二、爬楼梯 三、扑克牌顺子 添加逗号_牛客题霸_牛客网 (nowcoder.com) 一、添加逗号 没啥注意读题就是 注意逗号是从后往前加&#xff0c;第一位如果是3的倍数不需要加逗号&#xff0c;备注里面才是需要看的 count计数 是三的倍数就加逗号&#xff0c…

Win11+VS2022+CGAL5.6配置

1. CGAL库简介 CGAL&#xff08;Computational Geometry Algorithms Library&#xff09;是一个开源的计算几何算法库&#xff0c;主要用于处理几何问题和相关算法的实现。它提供了丰富的几何数据结构和高效算法&#xff0c;覆盖点、线、多边形、曲面等基本几何对象的表示与操…

【Linux】MAC帧

目录 一、MAC帧 &#xff08;一&#xff09;IP地址和MAC地址 &#xff08;二&#xff09;MAC帧格式 &#xff08;三&#xff09;MTU对IP协议的影响、 &#xff08;四&#xff09;MTU对UDP协议的影响 &#xff08;五&#xff09;MTU对TCP协议的影响 二、以太网协议 &…

Codeforces Round 1013 (Div. 3)(A-F)

题目链接&#xff1a;Dashboard - Codeforces Round 1013 (Div. 3) - Codeforces A. Olympiad Date 思路 找到第一个位置能凑齐01032025的位置 代码 void solve(){int n;cin>>n;vi a(n10);int id0;map<int,int> mp;for(int i1;i<n;i){cin>>a[i];mp[a…

Vite 与 Nuxt 深度对比分析

一、核心定位差异 二、核心功能对比 渲染能力 Vite&#xff1a;默认仅支持客户端渲染&#xff08;CSR&#xff09;&#xff0c;需通过插件&#xff08;如vite-plugin-ssr&#xff09;实现 SSR/SSG&#xff0c;但配置灵活 Nuxt&#xff1a;原生支持 SSR&#xff08;服务端渲…

通过一个led点灯的demo来熟悉openharmony驱动编写的过程(附带hdf详细调用过程)

概述 本应用程序(led_rgb)是在上实现直接通过消息机制与内核驱动进行交互&#xff0c;设置RGB三色灯的亮灯行为。我从网上随便找了个demo测试了一下&#xff0c;坑了三天…&#xff0c;整个状态如下图&#xff0c;同时也迫使我深度梳理了一下整个流程框架。直到绝望的时候&…

pycharm2024.1.1版本_jihuo

目录 前置&#xff1a; 步骤&#xff1a; step one 下载软件 step two 卸载旧版本 1 卸载软件 2 清除残余 step three 下载补丁 step four 安装2024.1.1版本软件 step five 安装补丁 1 找位置放补丁 2 自动设置环境变量 step six 输入jihuo码 前置&#xff1a; 之…

目标检测20年(四)——最终章

欢迎各位读者尽情阅读前三篇文献解读。这一篇将会介绍文献的第五部分&#xff1a;目标检测近些年的新技术发展以及第六部分&#xff1a;总结与未来展望。这也是本篇论文解读的最后一篇文章。 目录 五、目标检测最新进展 5.1 不采用滑动窗口的检测 5.2 旋转和尺度变化的鲁棒性…

【Linux】POSIX信号量与基于环形队列的生产消费者模型

目录 一、POSIX信号量&#xff1a; 接口&#xff1a; 二、基于环形队列的生产消费者模型 环形队列&#xff1a; 单生产单消费实现代码&#xff1a; RingQueue.hpp&#xff1a; main.cc&#xff1a; 多生产多消费实现代码&#xff1a; RingQueue.hpp&#xff1a; main.…

Spring Boot 连接 MySQL 配置参数详解

Spring Boot 连接 MySQL 配置参数详解 前言参数及含义常用参数及讲解和示例useUnicode 参数说明&#xff1a; 完整配置示例注意事项 前言 在 Spring Boot 中使用 Druid 连接池配置 MySQL 数据库连接时&#xff0c;URL 中 ? 后面的参数用于指定连接的各种属性。以下是常见参数…

[linux] linux基本指令 + shell + 文件权限

目录 1. Linux的认识 1.1. Linux的应用场景 1.2. Linux的版本问题 1.3. 操作系统的认识 1.4. 常用快捷键 2. 常用指令介绍 2.1. ADD 2.1.1. touch [file] 2.1.1.1. 文件的属性信息 2.1.2. mkdir [directory] 2.1.3. cp [file/directory] 2.1.4. echo [file] 2.1.4.…

Python实现小红书app版爬虫

简介&#xff1a;由于数据需求的日益增大&#xff0c;小红书网页版已经不能满足我们日常工作的需求&#xff0c;为此&#xff0c;小编特地开发了小红书手机版算法&#xff0c;方便大家获取更多的数据&#xff0c;提升工作效率。 手机版接口主要包括&#xff1a;搜素&#xff0…