算法-二分专题

文章目录

  • 概念
  • 应用场景
  • 代码模板
  • OJ练习
    • 寻找指定元素1
      • 题目描述
      • 输入描述
      • 输出描述
      • 样例
      • 题解
    • 寻找指定元素2
      • 题目描述
      • 输入描述
      • 输出描述
      • 样例
      • 题解
    • 寻找指定元素3
      • 题目描述
      • 输入描述
      • 输出描述
      • 样例
      • 题解
    • 寻找指定元素4
      • 题目描述
      • 输入描述
      • 输出描述
      • 样例
      • 题解
    • 寻找指定元素5
      • 题目描述
      • 输入描述
      • 输出描述
      • 样例
      • 题解
    • 寻找指定元素6
      • 题目描述
      • 输入描述
      • 输出描述
      • 样例
      • 题解

概念

二分查找(Binary Search)算法,也叫折半查找算法。二分查找的思想非常简单,有点类似分治的思想。二分查找针对的是一个有序的数据集合,每次都通过跟区间的中间元素对比,将待查找的区间缩小为之前的一半,直到找到要查找的元素,或者区间被缩小为 0。

为了方便理解,我们以数组

1,3,5,7,11,13,17,19,23,29,31,37,41,43,53,59,在数组中查找37为例,制作了一张查找过程动图,其中low标示左下标,high标示右下标,mid标示中间值下标
在这里插入图片描述
可以看出二分查找在查找数字 37 时只需3次,而顺序查找 查找37时需要11次。

应用场景

二分搜索用于在一个单调或者局部单调有序数组中查找一个符合某些条件的值,时间复杂度为O(logN)

代码模板

int BinarySearch(int *a,int len,int key){
	int low = 0,high = len-1,mid;
	while(low<=high){
		mid = (low+high)/2;      //取中间位置
		if(a[mid] == key){
			return mid;          //查找成功并返回所在位置
		}
		else if( key < a[mid] ){   
			high = mid - 1;	     //从前半部分查找
		}
		else{
			low = mid + 1;	     //从后半部分查找
		}
	}
}

OJ练习

寻找指定元素1

题目描述

在一个严格递增序列A中寻找一个指定元素x,如果能找到,那么输出它的下标;如果不能找到,那么输出。

注:使用二分法实现。

输入描述

在这里插入图片描述

输出描述

如果能找到x,那么输出它的下标;否则输出-1。

样例

样例1

输入

5 3
1 2 3 5 8

输出

2

样例2

输入

5 6
1 2 3 5 8

输出

-1

题解

这题就是直接套模板

#include<bits/stdc++.h>
using namespace std;
const int N = 1e6;
int A[N];

int BinarySearch(int *a,int len,int key){
	int low = 0,high = len-1,mid;
	while(low<=high){
		mid = (low+high)/2;      //取中间位置
		if(a[mid] == key){
			return mid;          //查找成功并返回所在位置
		}
		else if( key < a[mid] ){   
			high = mid - 1;	     //从前半部分查找
		}
		else{
			low = mid + 1;	     //从后半部分查找
		}
	}
	return -1;
}

int main(){
	int n,x;
	cin >> n >> x;
	for(int i = 0;i < n;i ++){
		cin >> A[i];
	}
	cout << BinarySearch(A,n,x);
	return 0;
}

寻找指定元素2

题目描述

在一个严格递减序列A中寻找一个指定元素x,如果能找到,那么输出它的下标;如果不能找到,那么输出-1。

注:使用二分法实现。

输入描述

在这里插入图片描述

输出描述

如果能找到x,那么输出它的下标;否则输出-1。

样例

样例1

输入

5 3
8 5 3 2 1

输出

2

样例2

输入

5 6
8 5 3 2 1

输出

-1

题解

这个就是在板子基础上,把大于号小于反过来就行了,递增变递减

#include<bits/stdc++.h>
using namespace std;
const int N = 1e6;
int A[N];

int BinarySearch(int *a,int len,int key){
	int low = 0,high = len-1,mid;
	while(low<=high){
		mid = (low+high)/2;      //取中间位置
		if(a[mid] == key){
			return mid;          //查找成功并返回所在位置
		}
		else if( key > a[mid] ){   
			high = mid - 1;	     //从前半部分查找
		}
		else{
			low = mid + 1;	     //从后半部分查找
		}
	}
	return -1;
}

int main(){
	int n,x;
	cin >> n >> x;
	for(int i = 0;i < n;i ++){
		cin >> A[i];
	}
	cout << BinarySearch(A,n,x);
	return 0;
}

寻找指定元素3

题目描述

在一个递增序列A(可能存在重复元素)中寻找第一个大于等于x的序列下标。

注:使用二分法实现。

输入描述

在这里插入图片描述

输出描述

输出第一个大于等于x的序列下标。

样例

样例1

输入

5 5
1 4 5 5 7

输出

2

解释

序列中存在5,所以第一个大于等于5的元素就是5,对应的序列下标是2

样例2

输入

5 6
1 4 5 5 7

输出

4

解释

序列中不存在6,第一个大于等于6的元素是7,对应的序列下标是4

样例3

输入

5 8
1 4 5 5 7

输出

5

解释
序列中所有元素都小于8,因此第一个大于等于8的序列下标是5

题解

循环条件为low<high而非之前的low<=high,这是由问题本身决定的。在上一个问题中,需要当元素不存在时返回-1,这样当low>high时[low,high]这个区间就不存在了,可以此作为元素不存在的判定原则,因此low<=high满足时循环应当一致执行;但是如果想要返回第一个大于等于x的元素的位置,就不需要判断x本身是否存在,因为就算它不存在,返回的也是“假设它存在,它应该在的位置”,于是当low==high时,[low,high]刚好能夹出唯一的位置,就是需要的结果,因此只需要当low<high时让循环一直执行即可。

由于当low==high时while循环停止,因此最后的返回值既可以是low,也可以是high。

二分的初始区间应当能覆盖到所有可能返回的结果。首先,二分下界是0是显然的,但是二分上界是n-1还是n呢?考虑到要查询元素有可能比序列中的所有元素都要大,此时应当返回n(即假设它存在,它应该在的位置),因此二分上界是n,故二分的初始区间为[low,high]=[0,n]

#include<bits/stdc++.h>
using namespace std;
const int N = 1e6;
int A[N];

int BinarySearch(int *a,int len,int key){
	int low = 0,high = len;
	while(low<high){
		int mid = (low+high)/2;      
		if(a[mid] >= key){
			high = mid;         
		}
		else{   
			low = mid + 1;	     
		}
	}
	return low;
}

int main(){
	int n,x;
	cin >> n >> x;
	for(int i = 0;i < n;i ++){
		cin >> A[i];
	}
	cout << BinarySearch(A,n,x);
	return 0;
}

寻找指定元素4

题目描述

在一个递增序列A(可能存在重复元素)中寻找第一个大于x的序列下标。

注:使用二分法实现。

输入描述

在这里插入图片描述

输出描述

输出第一个大于x的序列下标。

样例

样例1

输入

5 5
1 4 5 5 7

输出

4

解释

序列中存在5,所以第一个大于等于5的元素就是5,对应的序列下标是2

样例2

输入

5 6
1 4 5 5 7

输出

4

解释

序列中不存在6,第一个大于等于6的元素是7,对应的序列下标是4

样例3

输入

5 8
1 4 5 5 7

输出

5

解释
序列中所有元素都小于8,因此第一个大于等于8的序列下标是5

题解

此题和上题类似,只需要把等于号去掉

#include<bits/stdc++.h>
using namespace std;
const int N = 1e6;
int A[N];

int BinarySearch(int *a,int len,int key){
	int low = 0,high = len;
	while(low<high){
		int mid = (low+high)/2;      
		if(a[mid] > key){
			high = mid;         
		}
		else{   
			low = mid + 1;	     
		}
	}
	return low;
}

int main(){
	int n,x;
	cin >> n >> x;
	for(int i = 0;i < n;i ++){
		cin >> A[i];
	}
	cout << BinarySearch(A,n,x);
	return 0;
}

寻找指定元素5

题目描述

在一个递增序列
A(可能存在重复元素)中寻找一个指定元素x,如果能找到,那么输出第一个x的下标;如果不能找到,那么输出-1。

注:使用二分法实现。

输入描述

在这里插入图片描述

输出描述

如果能找到x,那么输出第一个x的下标;否则输出-1。

样例

样例1

输入

5 5
1 5 5 5 7

输出

1

解释

序列中存在三个5,第一个5的序列下标是1

样例2

输入

5 6
1 5 5 5 7

输出

-1

解释

序列中不存在6,因此输出-1

题解

因为会有很多个重复数据,这里只要出现的第一个,那么我们可以改变二分时候查找到key的条件,我们现在不让他查找到就结束,如果查找到了,就让他往左缩短,因为要找的是第一个,如果找最后一个就往右缩短就行了。

需要注意的是,如果没有查找到key,我们需要额外一个bool类型变量,用来判断是否找到过,找到过那个位置就是high+1.没找到就返回-1,可以用三目运算符实现。

#include<bits/stdc++.h>
using namespace std;
const int N = 1e6;
bool isFound = false;
int A[N];

int BinarySearch(int *a,int len,int key){
	int low = 0,high = len-1;
	while(low<=high){
		int mid = (low+high)/2;      
		if(a[mid] == key){
			high = mid-1;     
            isFound = true;    
		}
		else if( key < a[mid] ){   
			high = mid - 1;	    
		}
		else{
			low = mid + 1;	   
		}
	}
	return isFound==true?high+1:-1;
}

int main(){
	int n,x;
	cin >> n >> x;
	for(int i = 0;i < n;i ++){
		cin >> A[i];
	}
	cout << BinarySearch(A,n,x);
	return 0;
}

寻找指定元素6

题目描述

在一个递增序列A(可能存在重复元素)中寻找一个指定元素x,如果能找到,那么输出最后一个x的下标;如果不能找到,那么输出-1。

注:使用二分法实现。

输入描述

在这里插入图片描述

输出描述

如果能找到x,那么输出最后一个x的下标;否则输出-1。

样例

样例1

输入

5 5
1 5 5 5 7

输出

3

解释

序列中存在三个5,最后一个5的序列下标是3

样例2

输入

5 6
1 5 5 5 7

输出

-1

解释

序列中不存在6,因此输出-1

题解

#include<bits/stdc++.h>
using namespace std;
const int N = 1e6;
bool isFound = false;
int A[N];

int BinarySearch(int *a,int len,int key){
	int low = 0,high = len-1;
	while(low<=high){
		int mid = (low+high)/2;      
		if(a[mid] == key){
			low = mid+1;     
			isFound = true;    
		}
		else if( key < a[mid] ){   
			high = mid - 1;	    
		}
		else{
			low = mid + 1;	   
		}
	}
	return isFound==true?low-1:-1;
}

int main(){
	int n,x;
	cin >> n >> x;
	for(int i = 0;i < n;i ++){
		cin >> A[i];
	}
	cout << BinarySearch(A,n,x);
	return 0;
}

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

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

相关文章

SpringBoot教程(十四) | SpringBoot集成Redis(全网最全)

SpringBoot教程(十四) | SpringBoot集成Redis(全网最全) 一、Redis集成简介 Redis是我们Java开发中&#xff0c;使用频次非常高的一个nosql数据库&#xff0c;数据以key-value键值对的形式存储在内存中。redis的常用使用场景&#xff0c;可以做缓存&#xff0c;分布式锁&…

Java多线程——并发和并行、实现方法

多线程 并发和并行 实现方法 代码演示 方式一 package com.qiong.thread1;public class MyThread extends Thread{Overridepublic void run() {for (int i 0; i < 20; i) {System.out.println(getName() "Hello World");}} }package com.qiong.thread1;public…

随心玩玩(十二)通义千问——LLM大模型微调

写在前面&#xff1a;使劲的摸鱼&#xff0c;摸到的鱼才是自己的~ 文章目录 简介环境配置模型加载jupyter远程配置快速使用微调示例部署方案总结附录&#xff1a; ReAct Prompting 示例准备工作一&#xff1a;样例问题、样例工具准备工作二&#xff1a;ReAct 模版步骤一&#x…

高通sm7250与765G芯片是什么关系?(一百八十一)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

【翻译】Qt Designer 如何使用资源文件

原文地址&#xff1a;https://doc.qt.io/qt-6/designer-resources.html Qt的资源浏览器是用于管理应用程序资源的工具&#xff0c;可以让开发者方便地查看和管理应用程序中的各种资源文件&#xff0c;例如图像、字体、布局文件、对话框等。 资源浏览器提供了一个可视化的界面&…

【BBuf的CUDA笔记】十二,LayerNorm/RMSNorm的重计算实现

带注释版本的实现被写到了这里&#xff1a;https://github.com/BBuf/how-to-optim-algorithm-in-cuda/tree/master/apex 由于有很多个人理解&#xff0c;读者可配合当前文章谨慎理解。 0x0. 背景 我也是偶然在知乎的一个问题下看到这个问题&#xff0c;大概就是说在使用apex的…

移动端开发进阶之蓝牙通讯(二)

移动端开发进阶之蓝牙通讯&#xff08;二&#xff09; 蓝牙广播是一种无线通讯技术&#xff0c;通过无线电波传输数据&#xff1b; 在蓝牙低功耗&#xff08;BLE&#xff09;协议中&#xff0c;广播通信是其重要组成部分&#xff0c;主要有两类使用场景&#xff1a; 单一方向的…

QT-day6

作业1&#xff1a;数据库增删查改 #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);if (!db.contains("stu.db")){db QSqlDatabase::addDatabase(&q…

2024年腾讯云服务器多少钱1个月?

2024年腾讯云服务器多少钱1个月&#xff1f;5元一个月&#xff0c;62元一年&#xff0c;更多腾讯云服务器精准报价。腾讯云服务器租用优惠价格表&#xff1a;轻量应用服务器2核2G3M价格62元一年、2核2G4M价格118元一年&#xff0c;540元三年、2核4G5M带宽218元一年&#xff0c;…

Uibot (RPA设计软件)Mage AI智能识别(发票识别)———课前材料五

微信群发助手机器人的小项目友友们可以参考小北的课前材料二博客~ (本博客中会有部分课程ppt截屏,如有侵权请及请及时与小北我取得联系~&#xff09; 紧接着小北的前两篇博客&#xff0c;友友们我们即将开展新课的学习~RPA 培训前期准备指南——安装Uibot(RPA设计软件&#x…

搜维尔科技:【简报】元宇宙数字人赛道,《寒朵鹿》赏析!

寒朵鹿的外观是柔和无攻击性的小鹿拟人样&#xff0c;头上长有一对鹿角及鹿耳&#xff0c;虽然绝大部分雌鹿并不会长角&#xff0c;但由于寒朵鹿是AI的智能机器人&#xff0c;所以为了依照普遍大众对鹿的印象依旧帮她加上了角。 学校&#xff1a; 台北商业大学 选手&#xff1…

【翻译】在Qt Designer中创建主窗口(Main Windows)

原文地址&#xff1a;https://doc.qt.io/qt-6/designer-creating-mainwindows.html Qt Designer 可用于为不同用途创建用户界面&#xff0c;并为每个用户界面提供不同类型的模板。主窗口模板用于创建具有菜单栏、工具栏和停靠窗口部件的应用程序窗口。 通过打开文件菜单并选择…

vue3项目部署到服务器,刚打开没事,一刷新页面就404

vue3项目部署到服务器&#xff0c;刚打开没事&#xff0c;一刷新页面就404 vue3项目&#xff0c;在本地调试时各方面都没毛病&#xff0c;刷新也没毛病&#xff0c;但是&#xff0c;扔到服务器上&#xff0c;第一次打开是正常的&#xff0c;再刷新下就404了&#xff0c;不知道什…

java+vue基于Spring Boot的渔船出海及海货统计系统

该渔船出海及海货统计系统采用B/S架构、前后端分离进行设计&#xff0c;并采用java语言以及springboot框架进行开发。该系统主要设计并完成了管理过程中的用户注册登录、个人信息修改、用户信息、渔船信息、渔船航班、海货价格、渔船海货、非法举报、渔船黑名单等功能。该系统操…

含PEMFC的热电联供系统能量管理策略Simulink仿真

1.光伏发电系统 在直流微电网中&#xff0c;光伏电池系统经过升压DC/DC变换器接入直流微电网提供功率。在不同的系统运行条件下&#xff0c;光伏电池系统有三种工作模式&#xff1a;MPPT 模式、下垂模式和空闲模式。由于光伏阵列的输出特性随着环境条件影响&#xff0c;光伏电池…

docker-compose安装HertzBeat赫兹跳动监控H3C交换机

前面我们用docker方式安装了HertzBeat&#xff0c;现在我们自己写个docker-compose.yml文件、创建文件直接docker-compose up -d直接启动运行 使用docker-compose需要先安装docker和docker-compose1、输入以下两段命令 mkdir 123 && cd 123 && mkdir data &a…

Spring Cloud + Vue前后端分离-第12章 通用权限设计

源代码在GitHub - 629y/course: Spring Cloud Vue前后端分离-在线课程 Spring Cloud Vue前后端分离-第12章 通用权限设计 这一章我们不依赖第三方框架&#xff0c;我会从权限相关表的设计&#xff0c;到权限的配置&#xff0c;到权限的拦截&#xff0c;带大家一步一步的做出…

领域驱动设计——DDD领域驱动设计进阶

摘要 进阶篇主要讲解领域事件、DDD 分层架构、几种常见的微服务架构模型以及中台设计思想等内容。如何通过领域事件实现微服务解耦&#xff1f;、怎样进行微服务分层设计&#xff1f;、如何实现层与层之间的服务协作&#xff1f;、通过几种微服务架构模型的对比分析&#xff0…

【LeetCode】206. 反转链表(简单)——代码随想录算法训练营Day03

题目链接&#xff1a;206. 反转链表 题目描述 给你单链表的头节点 head &#xff0c;请你反转链表&#xff0c;并返回反转后的链表。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[5,4,3,2,1] 示例 2&#xff1a; 输入&#xff1a;head [1,2] 输…

多目标优化(Python):多目标粒子群优化算法(MOPSO)求解ZDT1、ZDT2、ZDT3、ZDT4、ZDT6(提供Python代码)

一、多目标粒子群优化算法 多目标粒子群优化算法&#xff08;MOPSO&#xff09;是一种用于解决多目标优化问题的进化算法。它基于粒子群优化算法&#xff08;PSO&#xff09;&#xff0c;通过引入多个目标函数和非支配排序来处理多目标问题。 MOPSO的基本思想是将问题转化为在…