[二分查找] 旋转数组

1. (严格递增序列)旋转数组的元素查找

 简单来说分为三种情况进行分析

1. 整个旋转数组单调递增

根据x和A[mid]的大小关系,更迭范围。

        // 1. 整个旋转数组单调递增if (A[left]<A[right]){if (A[mid] == x)return mid;else if (x < A[mid])right = mid-1;else if (x > A[mid])left = mid+1;}

2. 旋转数组分为两个递增序列,mid位于第一个递增序列当中

mid将旋转数组分为两块区间,但第一块区间的值的条件并不是简单的x<A[mid],因为小于A[mid]的元素还有可能为最下面的区间,如图。

        // 2. 旋转数组分为两个递增序列,mid位于第一个递增序列当中if (A[mid]>A[left]){if (x == A[mid])return mid;else if (x<A[mid] && x >= A[left]){right = mid-1;}else{left = mid+1;}}

 3. mid位于第二个递增序列当中

        // 3. 旋转数组分为两个递增序列,mid位于第二个递增序列当中if (A[mid]<A[left]){if (x == A[mid])return mid;else if (x>A[mid] && x<=A[right]){left = mid+1;}else {right = mid-1; }}

最后的总代码:

#include <cstdio>const int N= 1e5+10;
int A[N];
int n,x;
int binary_search(int A[],int left,int right,int x){int mid;while (left < right){mid = left + (right-left)/2;// 1. 整个旋转数组单调递增if (A[left]<A[right]){if (A[mid] == x)return mid;else if (x < A[mid])right = mid-1;else if (x > A[mid])left = mid+1;}// 2. 旋转数组分为两个递增序列,mid位于第一个递增序列当中if (A[mid]>A[left]){if (x == A[mid])return mid;else if (x<A[mid] && x >= A[left]){right = mid-1;}else{left = mid+1;}}// 3. 旋转数组分为两个递增序列,mid位于第二个递增序列当中if (A[mid]<A[left]){if (x == A[mid])return mid;else if (x>A[mid] && x<=A[right]){left = mid+1;}else {right = mid-1; }}}if (A[left]==x)return left;return -1;
}
int main(){scanf("%d%d",&n,&x);for (int i=0;i<n;i++)scanf("%d",&A[i]);printf("%d",binary_search(A,0,n-1,x));return 0;}

2.(非递减序列)旋转数组的元素查找

思路一致,由于会出现重复的元素,因此,对寻找第一个x的寻找条件进行修改即可。

不过由于非递减的条件不好写,因此我们可以用else来表示

#include <cstdio>const int N= 1e5+10;
int A[N];
int n,x;
int binary_search(int A[],int left,int right,int x){int mid;while (left < right){mid = left + (right-left)/2;// 2. 旋转数组分为两个非递减序列,mid位于第一个非递减序列当中if (A[mid]>A[left]){if (x == A[mid])right = mid;else if (x<A[mid] && x >= A[left]){right = mid-1;}else{left = mid+1;}}else if (A[mid]<A[left]){// 3. 旋转数组分为两个递增序列,mid位于第二个递增序列当中if (x == A[mid])right=mid;else if (x>A[mid] && x<=A[right]){left = mid+1;}else {right = mid-1;}}else {//1. 整个旋转数组非递减if (A[mid] == x)right = mid;else if (x < A[mid])right = mid-1;else if (x > A[mid])left = mid+1;}}if (A[left]==x)return left;return -1;
}
int main(){scanf("%d%d",&n,&x);for (int i=0;i<n;i++)scanf("%d",&A[i]);printf("%d",binary_search(A,0,n-1,x));return 0;}

3. 旋转数组的最小值,通过数组左端元素判断最小值出现的位置

两个代码相同。需要注意 A[left] == A[mid] 的情况,最小值在右侧区间中

#include <cstdio>const int N= 1e5+10;
int A[N];
int n;
int binary_search(int A[],int left,int right){int mid;while (left < right){mid = left + (right-left)/2;// 1. 整个旋转数组单调递增if (A[left]<A[right]){return A[left];}// 2. 旋转数组分为两个单调递增序列,mid位于第一个单调递增序列当中if (A[mid]>A[left]){left = mid+1;}else if (A[mid]<A[left]){// 3. 旋转数组分为两个递增序列,mid位于第二个递增序列当中right = mid;}else if(A[mid]==A[left]){// A[left] == A[mid] 的情况,最小值在右侧区间中left = mid+1;}//printf("%d,%d\n",left,right);}return A[left];
}
int main(){scanf("%d",&n);for (int i=0;i<n;i++)scanf("%d",&A[i]);printf("%d",binary_search(A,0,n-1));return 0;}

4. 旋转数组的中位数

#include <cstdio>const int N= 1e5+10;
int A[N];
int n;
int binary_search(int A[],int left,int right){int mid;while (left < right){mid = left + (right-left)/2;// 1. 整个旋转数组单调递增if (A[left]<A[right]){return left;}// 2. 旋转数组分为两个单调递增序列,mid位于第一个单调递增序列当中if (A[mid]>A[left]){left = mid+1;}else if (A[mid]<A[left]){// 3. 旋转数组分为两个递增序列,mid位于第二个递增序列当中right = mid;}else if(A[mid]==A[left]){// A[left] == A[mid] 的情况,最小值在右侧区间中left = mid+1;}//printf("%d,%d\n",left,right);}return left;
}
int main(){scanf("%d",&n);for (int i=0;i<n;i++)scanf("%d",&A[i]);int minpos = binary_search(A,0,n-1);//printf("%d",minpos);if (n%2==0){printf("%.1f",(A[(minpos+n/2)%n]+A[(minpos+n/2)%n-1])/2.0);}else {printf("%.1f",A[(minpos+n/2)%n]/1.0);}return 0;}

 重点在于后面中位数的求解

    if (n%2==0){printf("%.1f",(A[(minpos+n/2)%n]+A[(minpos+n/2)%n-1])/2.0);}else {printf("%.1f",A[(minpos+n/2)%n]/1.0);}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Linux】Libevent相关小知识总结

Libevent是基于事件的&#xff0c;也就是说&#xff0c;相当于去注册一个事件&#xff0c;当这个事件发生的话&#xff0c;那么就会调用回调函数。

25.CSS自定义形状按钮与悬停效果

效果 源码 <!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>CSS Custom Shape Button</title><link rel="stylesheet" href="style.css"> </head> <body&…

操作系统的发展和分类

注意&#xff1a;每个阶段的主要优点都是解决了上个阶段的缺点 1.手工操作阶段 概括&#xff1a;一个用户在一段时间内独占全机&#xff0c;导致资源利用率极低&#xff0c;用户输入指令给机器&#xff0c;然后机器运行响应给用户。 2.批处理阶段 2.1单道批处理系统 优点&…

docker命令学习

docker vscode插件出现的问题 docker命令 docker images &#xff08;查看所有的镜像&#xff09; docker ps -a &#xff08;查看所有的容器&#xff09; docker ps &#xff08;查看运行的容器&#xff09; docker run imageID docker run --gpus all --shm-size8g -it imag…

A Mathematical Framework for Transformer Circuits—Part (1)

A Mathematical Framework for Transformer Circuits 前言Summary of ResultsREVERSE ENGINEERING RESULTSCONCEPTUAL TAKE-AWAYS Transformer OverviewModel SimplificationsHigh-Level ArchitectureVirtual Weights and the Residual Stream as a Communication ChannelVIRTU…

16.WebSocket聊天室

基于SpringBoot 2.6.11 1.WebSocket WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议&#xff0c;可以在html页面直接使用。 WebSocket 使得客户端和服务器之间的数据交换变得更加简单&#xff0c;允许服务端主动向客户端推送数据。在 WebSocket A…

java对时间序列根据阈值进行连续性分片

问题描述&#xff1a;我需要对一个连续的时间戳list进行分片&#xff0c;分片规则是下一个数据比当前数据要大于某一个阈值则进行分片&#xff1b; 解决方式&#xff1a; 1、输入的有顺序的list &#xff0c;和需要进行分片的阈值 2、调用方法&#xff0c;填入该排序的list和阈…

docker安装redis,并挂载配置文件

1&#xff1a;下载镜像&#xff0c;不添加版本 默认下载最新的 docker pull redis下载成功后如图所示 2&#xff1a;下载redis配置文件&#xff0c;我是在docker中下载的&#xff0c;也可以使用文件上传工具将配置文件上传到自己指定的目录。 首先需要安装wget&#xff0c;否…

蓝牙发展现状

目录 一、产品分类1、Bluetooth经典2、Bluetooth低能耗(LE)3、二者差异 二、出货量三、未来需要加强的方向四、技术行业细分五、学习资料1、蓝牙官网2、大神博客——于忠军 一、产品分类 1、Bluetooth经典 Bluetooth Classic无线电&#xff0c;也被称为Bluetooth 基本速率/增强…

QT 界面相关操作

1> 创建自定义类时需要指定父类 2> 第一个界面的相关操作 #include "widget.h" #include<iostream> //printf #include<QDebug> //qDebuf #include<QIcon> //图标的头文件 using namespace std; //coutWidget::Widget(QWidget *…

go gin 自定义验证

我们上一篇已经提到了gin中binding时候可以指定json字段大小等限制&#xff0c;但是那个错误却是英文的&#xff0c;现在想搞成中文的&#xff0c;以便前端可读&#xff0c;demo如下 package mainimport ("net/http""reflect""github.com/gin-gonic/…

基于JAVA SpringBoot互联网就医门诊挂号管理系统

摘要 随着时代的发展,无线互联网技术的应用和普及给人们的生活带来了极大的改变,现在信息技术不仅可以提高我们的工作效率,还能有效的规避一些错误风险,节约人力成本。我国国民一方面对健康的要求越来越重视了&#xff0c;另一方面现代人的健康问题日益严重&#xff0c;所以医院…

Linux系统调试中出现核心转储(core dump)的问题

​ 大家好&#xff0c;我是ST。今天主要分享一下&#xff0c;Linux应用程序发生Segmentation fault段错误时&#xff0c;如何利用core dump文件定位错误。 核心转储 在 Linux 系统中&#xff0c;常将“主内存”称为核心(core)&#xff0c;而核心映像(core image) 就是 “进…

4.1 链式栈StackT

C关键词&#xff1a;内部类/模板类/头插 C自学精简教程 目录(必读) C数据结构与算法实现&#xff08;目录&#xff09; 栈的内存结构 空栈&#xff1a; 有一个元素的栈&#xff1a; 多个元素的栈&#xff1a; 成员函数说明 0 clear 清空栈 clear 函数负责将栈的对内存释放…

arduino仿真 SimulIDE1.0仿真器

SimulIDE 是一个开源的电子电路模拟器&#xff0c;支持模拟各种电子元器件的行为&#xff0c;可以帮助电子工程师和爱好者进行电路设计和测试。以下是 SimulIDE 的安装和使用说明&#xff1a; 安装 SimulIDE SimulIDE 可以在 Windows、Linux 和 Mac OS X 等操作系统上安装。您…

仿京东 项目笔记1

目录 项目代码1. 项目配置2. 前端Vue核心3. 组件的显示与隐藏用v-if和v-show4. 路由传参4.1 路由跳转有几种方式&#xff1f;4.2 路由传参&#xff0c;参数有几种写法&#xff1f;4.3 路由传参相关面试题4.3.1 路由传递参数&#xff08;对象写法&#xff09;path是否可以结合pa…

Qt应用开发(基础篇)——进度对话框 QProgressDialog

一、前言 QProgressDialog类继承于QDialog&#xff0c;是Qt设计用来反馈进度的对话框。 对话框QDialog QProgressDialog提供了一个进度条&#xff0c;表示当前程序的某操作的执行进度&#xff0c;让用户知道操作依旧在激活状态&#xff0c;配合按钮&#xff0c;用户就可以随时终…

【C++入门】string类常用方法(万字详解)

目录 1.STL简介1.1什么是STL1.2STL的版本1.3STL的六大组件1.4STL的缺陷 2.string类的使用2.1C语言中的字符串2.2标准库中的string类2.3string类的常用接口说明 &#xff08;只讲解最常用的接口&#xff09;2.3.1string类对象的常见构造2.3.2 string类对象的容量操作2.3.3string…

nnUNet v2数据准备及格式转换 (二)

如果你曾经使用过nnUNet V1&#xff0c;那你一定明白数据集的命名是有严格要求的&#xff0c;必须按照特定的格式来进行命名才能正常使用。 这一节的学习需要有数据&#xff0c;如果你有自己的数据&#xff0c;可以拿自己的数据来实验&#xff0c;如果没有&#xff0c;可以用十…

Python语音识别处理详解

概要 人们对智能语音助手的需求不断提高&#xff0c;语音识别技术也随之迅速发展。在这篇文章中&#xff0c;我们将介绍如何使用Python的SpeechRecognition和pydub等库来实现语音识别和处理&#xff0c;从而打造属于自己的智能语音助手。 1. 什么是语音识别&#xff1f; 语音…