蓝桥杯试题:二分查找

一、问题描述

给定 n 个数形成的一个序列 a,现定义如果一个连续子序列包含序列 a 中所有不同元素,则该连续子序列便为蓝桥序列,现在问你,该蓝桥序列长度最短为多少?

例如 1 2 2 2 3 2 2 1,包含 3 个不同的数 1,2,3,而 3 2 2 1 符合题目要求,因此答案为 4。

连续子序列:从序列 a 中选取若干个连续的数形成一个序列叫连续子序列。

输入格式

第一行输入一个整数 n,表示序列长度。

第二行输入 n 个元素。

输出格式

输出一个整数,表示最短的蓝桥序列长度。

样例输入

8
1 2 2 2 3 2 2 1

样例输出

4

二、代码展示 

import java.util.*;public class 全部都有的子序列_二分_滑动窗口 {public static void main(String[] args) {Scanner sc=new Scanner(System.in);int n= sc.nextInt();int []arr=new int[n];Set<Integer> set=new HashSet<>();for (int i = 0; i < n; i++) {arr[i]= sc.nextInt();set.add(arr[i]);}int l=0,r=n;int m=set.size();//set存储不重复的数字while(l<r){int mid=(l+r)/2;if(check(mid,arr,m)) r=mid;else l=mid+1;}System.out.println(l);}public static boolean check(int mid,int []arr,int m){//滑动窗口求解int n=arr.length;int []f=new int[1001];//记录出现频率int l=0,r=0;//双指针int ans=0;//统计当前窗口的不同元素数量while(r<n) {//右指针没有到达数组最右边f[arr[r]]++;//记录一个数的频率if(f[arr[r]]==1){ ans++;}if(r-l+1>mid) {//当区间距离>mid,说明此时并没有满足ans>=mf[arr[l]]--;//左指针对应减一if(f[arr[l]]==0){//说明之前只有一个,减去后变成零,这个时候一个数字消失,对应的ans应减一ans--;}l++;//左指针右移}r++;//右指针一直右移if(ans>=m) return true;}return false;}
}

这段代码的目标是找到数组中最短的连续子序列,该子序列包含数组中所有不同的元素。采用二分查找结合滑动窗口的方法,高效地确定最小长度。

代码结构

  1. 主函数

    • 读取输入数组,并用集合统计不同元素的数量m

    • 使用二分查找确定最小窗口长度,初始范围[0, n]

    • 每次计算中间值mid,调用check函数验证是否存在长度为mid的窗口满足条件。

    • 根据验证结果调整二分边界,最终输出最小长度l

  2. check函数

    • 使用滑动窗口和频率数组,判断是否存在长度不超过mid的子序列包含所有m个不同元素。

    • 维护窗口的左右指针lr,动态调整窗口大小。

    • 统计窗口内不同元素的数量ans,若达到m则返回true

详细步骤解释

1. 主函数逻辑
  • 输入处理:读取数组,并用HashSet统计不同元素的数量m

  • 二分查找初始化:左边界l设为0(最小可能长度),右边界r设为数组长度n(最大可能长度)。

  • 二分过程

    • 计算中间值mid = (l + r) / 2

    • 调用check(mid, arr, m)判断是否存在长度为mid的窗口。

    • 若存在,说明答案可能更小,调整右边界r = mid;否则调整左边界l = mid + 1

  • 终止条件:当l >= r时,l即为最小窗口长度。

2. check函数逻辑
  • 初始化:频率数组f记录元素出现次数,双指针lr初始为0,ans统计当前窗口的不同元素数量。

  • 滑动窗口过程

    1. 右指针扩展r右移,增加元素频率。若元素首次出现,ans加1。

    2. 窗口大小控制:当窗口长度超过mid时,左指针右移,减少对应元素频率。若元素频率减至0,ans减1。

    3. 条件检查:每次调整后,若ans >= m,立即返回true(存在满足条件的窗口)。

  • 遍历结束:若未找到满足条件的窗口,返回false

关键点分析

  • 二分查找的应用:利用答案的单调性(若长度为k可行,则更大长度必然可行),将时间复杂度优化至O(n log n)

  • 滑动窗口的灵活性:不固定窗口大小,而是允许在不超过mid的范围内动态调整,一旦满足条件立即返回。

  • 频率数组的作用:快速统计窗口内不同元素的数量,通过增减频率判断元素是否存在于当前窗口。

示例说明

假设数组为[1, 2, 3, 1, 2, 3, 4],不同元素数量m=4

  • 二分初始范围[0,7],第一次mid=3,检查是否存在长度为3的窗口包含4个不同元素(显然不可能)。

  • 调整边界,最终找到最小长度为4(如子序列[3, 1, 2, 4][1, 2, 3, 4])。

总结

该算法通过二分查找快速缩小搜索范围,结合滑动窗口高效验证,确保在合理时间复杂度内找到最优解。核心在于理解二分与滑动窗口的协同作用,以及频率数组维护窗口状态的技巧。

详解check方法:

1. 初始化参数


频率数组f:记录当前窗口中各元素的出现次数,索引对应元素值。

双指针l和r:初始均为0,分别表示窗口的左右边界。

计数器ans:统计窗口内不同元素的数量,初始为0。

2. 扩展右指针(窗口右移)


遍历数组:右指针r从0开始逐步右移,处理每个元素。

更新频率:将arr[r]的频率f[arr[r]]加1。
f[arr[r]]++;


唯一性判断:若该元素首次出现在窗口(频率由0变1),则ans加1。
if (f[arr[r]] == 1) ans++;


3. 收缩左指针(控制窗口大小)


窗口长度检查:当窗口长度r - l + 1超过mid时,需收缩左边界。
if (r - l + 1 > mid) {
    // 调整左指针
}
左移操作:

减少左指针元素频率:f[arr[l]]--。

唯一性减少:若元素频率减至0,说明该元素不再存在于窗口,ans减1。
if (f[arr[l]] == 0) ans--;
左指针右移:l++。

4. 实时检查条件满足


完成调整后:每次右指针移动并调整窗口后,立即检查ans是否达到m(所有不同元素数量)。
if (ans >= m) return true;
提前返回:一旦满足条件,立即返回true,无需遍历整个数组。

5. 遍历结束处理


循环结束仍未满足:若遍历完数组仍未找到符合条件的窗口,返回false。

6.示例说明


以数组[1,2,3,1,2,3,4]和mid=4为例:

窗口逐步扩展至包含元素1,2,3,此时ans=3。

右指针到元素4时,窗口包含1,2,3,4(ans=4),但窗口长度5超过mid=4。

收缩左指针至索引3,窗口变为[1,2,3,4],长度4满足条件,返回true。

边界情况处理
元素全相同:若数组元素全为5,m=1,窗口长度1即满足。

最小可能窗口:当mid=1且存在唯一元素时,直接返回true。

总结
check方法通过滑动窗口在O(n)时间内验证是否存在满足条件的子数组,结合二分查找高效定位最小长度,确保整体时间复杂度为O(n log n)。

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

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

相关文章

网络空间安全(7)攻防环境搭建

一、搭建前的准备 硬件资源&#xff1a;至少需要两台计算机&#xff0c;一台作为攻击机&#xff0c;用于执行攻击操作&#xff1b;另一台作为靶机&#xff0c;作为被攻击的目标。 软件资源&#xff1a; 操作系统&#xff1a;如Windows、Linux等&#xff0c;用于安装在攻击机和…

DeepSpeek服务器繁忙?这几种替代方案帮你流畅使用!(附本地部署教程)

作者&#xff1a;后端小肥肠 目录 1. 前言 2. 解决方案 2.1. 纳米AI搜索&#xff08;第三方平台&#xff09; 2.2. Github&#xff08;第三方平台&#xff09; 2.3. 硅基流动&#xff08;第三方API&#xff09; 3. 本地部署详细步骤 3.1. 运行配置需求 3.2. 部署教程 4…

prisma+supabase报错无法查询数据

解决方案&#xff0c;在DATABASE_URL后面增加?pgbouncertrue

c语言中return 数字代表的含义

return 数字的含义&#xff1a;表示函数返回一个整数值&#xff0c;通常用于向调用者&#xff08;如操作系统或其他程序&#xff09;传递程序的执行状态或结果。 核心规则&#xff1a; return 0&#xff1a; 含义&#xff1a;表示程序或函数正常结束。 示例&#xff1a; int m…

Spark内存迭代计算

一、宽窄依赖 窄依赖&#xff1a;父RDD的一个分区数据全部发往子RDD的一个分区 宽依赖&#xff1a;父RDD的一个分区数据发往子RDD的多个分区&#xff0c;也称为shuffle 二、Spark是如何进行内存计算的&#xff1f;DAG的作用&#xff1f;Stage阶段划分的作用&#xff1f; &a…

Linux知识-第一天

Linux的目录机构为一个树型结构 其没有盘符这个概念&#xff0c;只有一个根目录&#xff0c;所有文件均在其之下 在Linux系统中&#xff0c;路径之间的层级关系 使用 / 开头表示根目录&#xff0c;后面的表示层级关系 Linux命令入门 Linux命令基础 Linux命令通用格式 comman…

QT实现单个控制点在曲线上的贝塞尔曲线

最终效果: 一共三个文件 main.cpp #include <QApplication> #include "SplineBoard.h" int main(int argc,char** argv) {QApplication a(argc, argv);SplineBoard b;b.setWindowTitle("标准的贝塞尔曲线");b.show();SplineBoard b2(0.0001);b2.sh…

绘制思维导图画布选型

在实现思维导图/知识图谱的绘制时&#xff0c;选择合适的「画布」技术方案至关重要。以下是不同技术路线的对比分析和推荐方案&#xff1a; 一、技术方案对比 技术类型实现方式优点缺点适用场景普通DOM元素使用<div>CSS布局&#x1f539; 开发简单&#x1f539; 天然支持…

运维Splunk面试题及参考答案

目录 通过转发器导入数据的优势有哪些(如带宽控制、负载均衡等) 描述 Universal Forwarder 与 Heavy Forwarder 的差异 如何配置转发器实现数据的过滤与预处理 转发器的本地缓存机制如何保证数据可靠性 如何通过部署服务器统一管理多个转发器的配置 什么是 “查找表(L…

年后寒假总结及计划安排

年后寒假总结 年后主要学习了微服务&#xff0c;nacos (服务注册中心)&#xff0c;feign&#xff08;远程调用&#xff09;&#xff0c;网关&#xff0c;双token&#xff08;相较于之前更加规范&#xff0c;更加符合企业级&#xff09;&#xff0c;配置管理 &#xff0c;mybati…

word中交叉引用多篇参考文献格式[1-2]或[1-4]操作

划重点 更改左域名&#xff0c;输入 \#"[0" 更改中间域名&#xff0c;输入\#"" 更改右域名&#xff0c;输入 \#"0]" 1.[2-3]格式 首先点击交叉引用&#xff0c;引用参考文献 右击鼠标&#xff0c;点击切换域代码&#xff0c;对于左域名 删除 * …

【银河麒麟高级服务器操作系统】服务器测试业务耗时问题分析及处理全流程分享

更多银河麒麟操作系统产品及技术讨论&#xff0c;欢迎加入银河麒麟操作系统官方论坛 https://forum.kylinos.cn 了解更多银河麒麟操作系统全新产品&#xff0c;请点击访问 麒麟软件产品专区&#xff1a;https://product.kylinos.cn 开发者专区&#xff1a;https://developer…

opencv 模板匹配方法汇总

在OpenCV中&#xff0c;模板匹配是一种在较大图像中查找特定模板图像位置的技术。OpenCV提供了多种模板匹配方法&#xff0c;通过cv2.matchTemplate函数实现&#xff0c;该函数支持的匹配方式主要有以下6种&#xff0c;下面详细介绍每种方法的原理、特点和适用场景。 1. cv2.T…

NAT,代理服务,内网穿透

NAT 把报文的源IP替换为途径路由器的WAN口IP NAPT 如何将数据从公网转回给内网的主机&#xff1f;通过NAPT&#xff08;转换表&#xff09;来实现&#xff0c;每次从内网到公网&#xff0c;公网到内网都会根据转换表来进行 细节&#xff1a; NAT转换时&#xff0c;值替换源…

大模型分布式训练和优化

1. 分布式训练概述 随着语言模型参数量和所需训练数据量的急速增长,单个机器上有限的资源已无法满足大语言模型训练的要求。因此,设计分布式训练(Distributed Training)系统来解决海量的计算和内存资源需求问题变得至关重要。 分布式训练是指将机器学习或深度学习模型训练任…

第三方机构有哪些接口?

1&#xff0c;网银接口。2&#xff0c;代扣接口。3&#xff0c;POS接口。4&#xff0c;快捷支付接口 1.网银接口 第三方支付平台连接网银接口&#xff0c;进行支付跳转时&#xff0c;第三方支付平台充当了一个网关的角色&#xff0c;或者充当了银行的代 理。 2.代扣接口 银…

JUnit 版本影响 Bean 找不到

JUnit 版本影响 Bean 找不到 在为实现类编写测试类时&#xff0c;在测试类中使用构造器注入 Bean 时&#xff0c;提示找不到 Bean&#xff0c;代码如下&#xff1a; Service public class WeChatServiceImpl implements IWeChatService {Overridepublic String getNumber(Str…

夸父工具箱(安卓版) 手机超强工具箱

如今&#xff0c;人们的互联网活动日益频繁&#xff0c;导致手机内存即便频繁清理&#xff0c;也会莫名其妙地迅速填满&#xff0c;许多无用的垃圾信息悄然占据空间。那么&#xff0c;如何有效应对这一难题呢&#xff1f;答案就是今天新推出的这款工具软件&#xff0c;它能从根…

《深度学习进阶》第7集:深度实战 通过训练一个智能体玩游戏 来洞察 强化学习(RL)与决策系统

深度学习进阶 | 第7集&#xff1a;深度实战 通过训练一个智能体玩游戏 来洞察 强化学习&#xff08;RL&#xff09;与决策系统 在深度学习的广阔领域中&#xff0c;强化学习&#xff08;Reinforcement Learning, RL&#xff09;是一种独特的范式&#xff0c;它通过智能体与环境…

Linux端口映射

1. 方法一使用firewalld 1.1 开启伪装IP firewall-cmd --permanent --add-masquerade 1.2 配置端口转发&#xff0c;将到达本机的12345端口的访问转发到另一台服务器的22端口 firewall-cmd --permanent --add-forward-portport12345:prototcp:toaddr192.168.172.131:toport…