当前位置: 首页 > news >正文

突破编程_C++_查找算法(分块查找)

1 算法题 :使用分块算法在有序数组中查找指定元素

1.1 题目含义

在给定一个有序数组的情况下,使用分块查找算法来查找数组中是否包含指定的元素。分块查找算法是一种结合了顺序查找和二分查找思想的算法,它将有序数组划分为若干个块,每个块内的元素不必有序,但块与块之间必须保持有序。首先通过块之间的有序性来快速定位到目标元素可能存在的块,然后在该块内进行顺序查找。

1.2 示例

示例 1:
输入:

  • 有序数组:[1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29]
  • 块大小:5
  • 目标元素:17

输出:

  • 7

说明:

  • 数组被划分为 3 个块:[1, 3, 5, 7, 9]、[11, 13, 15, 17, 19] 和 [21, 23, 25, 27, 29]。通过比较块的首个元素,可以确定目标元素 17 在第二个块中。然后在该块内进行顺序查找,找到元素 17 的位置为 7(从 0 开始计数)。

示例 2:
输入:

  • 有序数组:[1, 4, 6, 9, 13, 16, 19, 22, 25, 28]
  • 块大小:4
  • 目标元素:10

输出:

  • -1

说明:

  • 数组被划分为 3 个块:[1, 4, 6, 9]、[13, 16, 19, 22] 和 [25, 28]。通过比较块的首个元素,可以确定目标元素 10 不在任何一个块中,因此整个数组中也不存在该元素。

示例 3:
输入:

  • 有序数组:[]
  • 块大小:10
  • 目标元素:50

输出:

  • -1

说明:

  • 有序数组为空,50 不存在于有序数组中,返回 -1。

2 解题思路

2.1 简单分块查找

(1)确定块数:

首先,根据给定的块大小,计算数组可以分成的块数。如果数组长度不是块大小的整数倍,则最后一个块的大小可能会小于块大小。

(2)定位目标块:

遍历数组中的块,通过比较每个块的首个元素和目标元素的大小关系,确定目标元素可能所在的块。如果目标元素小于当前块的首个元素,则目标元素不可能在当前块及之后的块中,可以提前结束遍历。

(3)块内顺序查找:

在定位到的目标块内,使用顺序查找算法来查找目标元素。从目标块的起始位置开始,逐个比较元素直到找到目标元素或遍历完整个块。

(4)返回结果:

如果找到了目标元素,则返回其在数组中的位置(索引)。如果遍历完所有块都没有找到目标元素,则返回表示未找到的标志(如-1)。

2.2 优化块内查找

这种思路在第一种的基础上,对块内查找进行了优化。

(1)确定块数和索引映射:

首先,像第一种思路一样确定块数。然后,可以建立一个索引映射关系,将每个元素映射到其所属的块和块内的相对位置。这样可以在定位到目标块后,直接计算出目标元素在块内的相对位置,减少不必要的比较操作。

(2)定位目标块:

这一步与第一种思路相同,通过比较块的首个元素和目标元素的大小关系,确定目标元素可能所在的块。

(3)块内直接定位:

利用索引映射关系,直接计算出目标元素在块内的相对位置。然后,通过该相对位置访问数组元素,检查是否为目标元素。

(4)返回结果:

如果找到了目标元素,则返回其在数组中的位置(索引)。如果遍历完所有块都没有找到目标元素,则返回表示未找到的标志(如-1)。

3 算法实现代码

3.1 简单分块查找

如下为算法实现代码:

#include <iostream>  
#include <vector>  
#include <cmath>  
#include <algorithm>  class Solution
{
public:// 分块查找算法实现  int blockSearch(const std::vector<int>& arr, int blockSize, int target) {int n = arr.size();int blockNum = (n + blockSize - 1) / blockSize; // 计算块数,向上取整  // 遍历块,定位目标元素可能所在的块  for (int i = 0; i < blockNum; ++i) {int blockStart = i * blockSize;int blockEnd = std::min(blockStart + blockSize, n); // 块内最后一个元素的索引  // 如果目标元素小于当前块的最小值,则目标元素不可能在当前块及之后的块中  if (target < arr[blockStart]) {break;}// 如果目标元素大于当前块的最大值,则继续查找下一个块  if (target > arr[blockEnd - 1]) {continue;}// 在目标块内进行顺序查找  for (int j = blockStart; j < blockEnd; ++j) {if (arr[j] == target) {return j; // 返回目标元素在数组中的位置  }}}return -1; // 未找到目标元素  }
};

这段代码首先计算了块数 blockNum,然后遍历每个块,通过比较块的首个元素 arr[blockStart] 和最后一个元素 arr[blockEnd - 1] 与目标元素 target 的大小关系,来确定目标元素可能所在的块。如果目标元素小于当前块的最小值,则它不可能在当前块及之后的块中,可以提前结束遍历。如果目标元素在当前块内,则在该块内进行顺序查找,直到找到目标元素或遍历完整个块。如果遍历完所有块都没有找到目标元素,则返回 -1 表示未找到。

调用上面的算法,并得到输出:

int main() 
{Solution s;std::vector<int> arr = { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29 };int blockSize = 5; // 块大小  int target = 17; // 目标元素  int index = s.blockSearch(arr, blockSize, target);if (index != -1) {std::cout << "Element found at index: " << index << std::endl;}else {std::cout << "Element not found in the array." << std::endl;}return 0;
}

上面代码的输出为:

Element found at index: 8

3.2 优化块内查找

如下为算法实现代码:

#include <iostream>  
#include <vector>  
#include <cmath>  
#include <algorithm>  
#include <unordered_map>  class Solution
{
public:// 分块查找算法实现  int blockSearch(const std::vector<int>& arr, int blockSize, int target) {int n = arr.size();int blockNum = (n + blockSize - 1) / blockSize; // 计算块数,向上取整  std::unordered_map<int, std::pair<int, int>> blockIndicesAndOffsets; // 存储块索引和块内偏移量  computeBlockIndicesAndOffsets(arr, blockSize, blockIndicesAndOffsets);// 遍历块,定位目标元素可能所在的块  for (int i = 0; i < blockNum; ++i) {int blockStart = i * blockSize;int blockEnd = std::min(blockStart + blockSize, n); // 块内最后一个元素的索引  // 如果目标元素小于当前块的最小值,则目标元素不可能在当前块及之后的块中  if (target < arr[blockStart]) {break;}// 如果目标元素大于当前块的最大值,则继续查找下一个块  if (target > arr[blockEnd - 1]) {continue;}// 检查目标元素是否在块内,并返回其位置  auto it = blockIndicesAndOffsets.find(target);if (it != blockIndicesAndOffsets.end() && it->second.first == i) {return blockStart + it->second.second; // 返回目标元素在数组中的位置  }}return -1; // 未找到目标元素 }private:// 计算并存储每个元素的块索引和块内偏移量  void computeBlockIndicesAndOffsets(const std::vector<int>& arr, int blockSize,std::unordered_map<int, std::pair<int, int>>& blockIndicesAndOffsets) {int n = arr.size();for (int i = 0; i < n; ++i) {int blockIndex = i / blockSize;int offset = i % blockSize;blockIndicesAndOffsets[arr[i]] = { blockIndex, offset };}}
};

在这个代码中,computeBlockIndicesAndOffsets 函数用于计算并存储每个元素的块索引和块内偏移量。optimizedBlockSearch 函数首先通过遍历块来定位目标元素可能所在的块,然后直接检查目标元素是否在预计算的块索引和偏移量映射中,并且其块索引与当前遍历的块索引相匹配。如果找到匹配项,则直接返回目标元素在数组中的位置。

注意:这种方法只适用于数组不会改变的情况,因为一旦数组发生变化,就需要重新计算块索引和偏移量。此外,如果数组非常大或者元素非常多,存储块索引和偏移量映射可能会消耗大量内存。因此,在实际应用中,需要根据具体情况权衡这种优化方法的利弊。

4 测试用例

以下是针对上面算法的测试用例,基本覆盖了各种情况:

(1)基础测试用例
输入:数组 arr = {1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29},块大小 blockSize = 5,目标元素 target = 17
输出:找到目标元素 17,位置为 8
说明:目标元素位于第三个块内,算法能够正确找到其位置。

(2)边界测试用例
输入:数组 arr = {1, 3, 5, 7, 9},块大小 blockSize = 3,目标元素 target = 1
输出:找到目标元素 1,位置为 0
说明:目标元素位于数组的第一个元素,算法能够正确处理边界情况。

输入:数组 arr = {1, 3, 5, 7, 9},块大小 blockSize = 3,目标元素 target = 9
输出:找到目标元素 9,位置为 4
说明:目标元素位于数组的最后一个元素,算法能够正确处理边界情况。

(3)块内查找测试用例
输入:数组 arr = {1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29},块大小 blockSize = 5,目标元素 target = 23
输出:找到目标元素 23,位置为 12
说明:目标元素位于第三个块内,但不是块的首个或末尾元素,算法能够在块内正确找到目标元素。

(4)未找到目标元素测试用例
输入:数组 arr = {1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29},块大小 blockSize = 5,目标元素 target = 30
输出:未找到目标元素 30
说明:目标元素不在数组中,算法能够正确处理未找到目标元素的情况。

(5)空数组测试用例
输入:数组 arr = {},块大小 blockSize = 5,目标元素 target = 1
输出:未找到目标元素 1
说明:数组为空,算法能够正确处理空数组的情况。

(6)单个块测试用例
输入:数组 arr = {1, 2, 3, 4, 5},块大小 blockSize = 5,目标元素 target = 3
输出:找到目标元素 3,位置为 2
说明:整个数组只包含一个块,算法能够正确处理单个块的情况。

相关文章:

突破编程_C++_查找算法(分块查找)

1 算法题 &#xff1a;使用分块算法在有序数组中查找指定元素 1.1 题目含义 在给定一个有序数组的情况下&#xff0c;使用分块查找算法来查找数组中是否包含指定的元素。分块查找算法是一种结合了顺序查找和二分查找思想的算法&#xff0c;它将有序数组划分为若干个块&#x…...

学习java第二十二天

IOC 容器具有依赖注入功能的容器&#xff0c;它可以创建对象&#xff0c;IOC 容器负责实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。通常new一个实例&#xff0c;控制权由程序员控制&#xff0c;而"控制反转"是指new实例工作不由程序员来做而是交给Sp…...

每天学习一个Linux命令之systemctl

每天学习一个Linux命令之systemctl 介绍 在Linux系统中&#xff0c;systemctl命令是Systemd初始化系统的核心管理工具之一。systemd是用来启动、管理和监控运行在Linux上的系统的第一个进程&#xff08;PID 1&#xff09;&#xff0c;它提供了一整套强大的工具和功能&#xf…...

【机器学习入门】人工神经网络(二)卷积和池化

系列文章目录 第1章 专家系统 第2章 决策树 第3章 神经元和感知机 识别手写数字——感知机 第4章 线性回归 第5章 逻辑斯蒂回归和分类 第5章 支持向量机 第6章 人工神经网络(一) 文章目录 系列文章目录前言一、卷积神经连接的局部性平移不变性 二、卷积处理图像的效果代码二、…...

公司内部局域网怎么适用飞书?

随着数字化办公的普及&#xff0c;企业对于内部沟通和文件传输的需求日益增长。飞书作为一款集成了即时通讯、云文档、日程管理、视频会议等多种功能的智能协作平台&#xff0c;已经成为许多企业提高工作效率的首选工具。本文将详细介绍如何在公司内部局域网中应用飞书&#xf…...

JVM的知识

什么是JVM 1.JVM&#xff1a; JVM其实就是运行在 操作系统之上的一个特殊的软件。 2.JVM的内部结构&#xff1a; &#xff08;1&#xff09;因为栈会将执行的程序弹出栈。 &#xff08;2&#xff09;垃圾99%的都是在堆和方法区中产生的。 类加载器&#xff1a;加载class文件。…...

大模型日报2024-03-24

利用LLMs评分及解释K-12科学答案 摘要: 本文研究了在K-12级科学教育中使用大型语言模型&#xff08;LLMs&#xff09;对短答案评分及解释。研究采用GPT-4结合少量样本学习和活跃学习&#xff0c;通过人机协作提供有意义的评估反馈。 MathVerse&#xff1a;多模态LLM解数学题效果…...

Android kotlin全局悬浮窗全屏功能和锁屏页面全屏悬浮窗功能一

1.前言 在进行app应用开发中,在实现某些功能中要求实现悬浮窗功能,分为应用内悬浮窗 ,全局悬浮窗和 锁屏页面悬浮窗功能 等,接下来就来实现这些悬浮窗全屏功能,首选看下第一部分功能实现 2.kotlin全局悬浮窗全屏功能和锁屏页面全屏悬浮窗功能一分析 悬浮窗是属于Androi…...

图像识别在安防领域的应用

图像识别技术在安防领域有着广泛的应用&#xff0c;它通过分析和理解图像中的视觉信息&#xff0c;为安防系统提供了强大的辅助功能。以下是一些主要的应用领域&#xff1a; 人脸识别&#xff1a;人脸识别技术是安防领域中最常见的应用之一。它可以帮助系统识别和验证个人身份…...

前端面试集中复习 - http篇

1. http请求方式 HTTP请求方式有哪些&#xff1a;GET POST PUT DELETE OPTIONS 1) GET POST 的区别&#xff1f; 场景上&#xff1a; GET 用于获取资源而不对服务器资源做更改提交的请求&#xff0c;多次执行结果一致。用于获取静态数据&#xff0c;幂等。 POST&#xff1…...

C++ - 类和对象(上)

目录 一、类的定义 二、访问限定符 public&#xff08;公有&#xff09; protected&#xff08;保护&#xff09; private&#xff08;私有&#xff09; 三、类声明和定义分离 四、外部变量和成员变量的区别与注意 五、类的实例化 六、类对象的模型 七、类的this指针…...

mysql基础4sql优化

SQL优化 插入数据优化 如果我们需要一次性往数据库表中插入多条记录&#xff0c;可以从以下三个方面进行优化。 insert into tb_test values(1,tom); insert into tb_test values(2,cat); insert into tb_test values(3,jerry);-- 优化方案一&#xff1a;批量插入数据 Inser…...

实现Spring Web MVC中的文件上传功能,并处理大文件和多文件上传

实现Spring Web MVC中的文件上传功能&#xff0c;并处理大文件和多文件上传 在Spring Web MVC中实现文件上传功能并处理大文件和多文件上传是一项常见的任务。下面是一个示例&#xff0c;演示如何在Spring Boot应用程序中实现这一功能&#xff1a; 添加Spring Web依赖&#x…...

搭建vite项目

文章目录 Vite 是一个基于 Webpack 的开发服务器&#xff0c;用于开发 Vue 3 和 Vite 应用程序 一、创建一个vite项目二、集成Vue Router1.安装 vue-routernext插件2.在 src 目录下创建一个名为 router 的文件夹&#xff0c;并在其中创建一个名为 index.js 的文件。在这个文件中…...

Docker 安装mysql 主从复制

目录 1 MySql主从复制简介 1.1 主从复制的概念 1.2 主从复制的作用 2. 搭建主从复制 2.1 pull mysql 镜像 2.2 新建主服务器容器实例 3307 2.2.1 master创建 my.cnf 2.2.2 重启master 2.2.3 进入mysql 容器&#xff0c;创建同步用户 2.3 新建从服务器容器实例 3308…...

GPT每日面试题—如何实现二分查找

充分利用ChatGPT的优势&#xff0c;帮助我们快速准备前端面试。今日问题&#xff1a;如何实现二分查找&#xff1f; Q&#xff1a;如果在前端面试中&#xff0c;被问到如何实现二分查找&#xff0c;如果回答比较好&#xff0c;给出必要的代码示例 A&#xff1a;当被问到如何实…...

机器学习神经网络由哪些构成?

机器学习神经网络通常由以下几个主要组件构成&#xff1a; 1. **输入层&#xff08;Input Layer&#xff09;**&#xff1a;输入层接受来自数据源&#xff08;例如图像、文本等&#xff09;的原始输入数据。每个输入特征通常表示为输入层中的一个节点。 2. **隐藏层&#xff…...

代码随想录算法训练营day19 | 二叉树阶段性总结

各个部分题目的代码题解都在我往日的二叉树的博客中。 (day14到day22) 目录 二叉树理论基础二叉树的遍历方式深度优先遍历广度优先遍历 求二叉树的属性二叉树的修改与制造求二叉搜索树的属性二叉树公共最先问题二叉搜索树的修改与构造总结 二叉树理论基础 二叉树的理论基础参…...

数据库引论:3、中级SQL

一些更复杂的查询表达 3.1 连接表达式 拼接多张表的几种方式 3.1.1 自然连接 natural join&#xff0c;自动连接在所有共同属性上相同的元组 join… using( A 1 , A 2 , ⋯ A_1,A_2,\cdots A1​,A2​,⋯):使用括号里的属性进行自然连接&#xff0c;除了这些属性之外的共同…...

毕业设计:日志记录编写(3/17起更新中)

目录 3/171.配置阿里云python加速镜像&#xff1a;2. 安装python3.9版本3. 爬虫技术选择4. 数据抓取和整理5. 难点和挑战 3/241.数据库建表信息2.后续进度安排3. 数据处理和分析 3/17 当前周期目标&#xff1a;构建基本的python环境&#xff1a;运行爬虫程序 1.配置阿里云pytho…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容

基于 ​UniApp + WebSocket​实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配​微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心

当仓库学会“思考”&#xff0c;物流的终极形态正在诞生 想象这样的场景&#xff1a; 凌晨3点&#xff0c;某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径&#xff1b;AI视觉系统在0.1秒内扫描包裹信息&#xff1b;数字孪生平台正模拟次日峰值流量压力…...

什么是Ansible Jinja2

理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具&#xff0c;可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板&#xff0c;允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板&#xff0c;并通…...

springboot整合VUE之在线教育管理系统简介

可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生&#xff0c;小白用户&#xff0c;想学习知识的 有点基础&#xff0c;想要通过项…...

微服务通信安全:深入解析mTLS的原理与实践

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、引言&#xff1a;微服务时代的通信安全挑战 随着云原生和微服务架构的普及&#xff0c;服务间的通信安全成为系统设计的核心议题。传统的单体架构中&…...

【安全篇】金刚不坏之身:整合 Spring Security + JWT 实现无状态认证与授权

摘要 本文是《Spring Boot 实战派》系列的第四篇。我们将直面所有 Web 应用都无法回避的核心问题&#xff1a;安全。文章将详细阐述认证&#xff08;Authentication) 与授权&#xff08;Authorization的核心概念&#xff0c;对比传统 Session-Cookie 与现代 JWT&#xff08;JS…...

在鸿蒙HarmonyOS 5中使用DevEco Studio实现指南针功能

指南针功能是许多位置服务应用的基础功能之一。下面我将详细介绍如何在HarmonyOS 5中使用DevEco Studio实现指南针功能。 1. 开发环境准备 确保已安装DevEco Studio 3.1或更高版本确保项目使用的是HarmonyOS 5.0 SDK在项目的module.json5中配置必要的权限 2. 权限配置 在mo…...

门静脉高压——表现

一、门静脉高压表现 00:01 1. 门静脉构成 00:13 组成结构&#xff1a;由肠系膜上静脉和脾静脉汇合构成&#xff0c;是肝脏血液供应的主要来源。淤血后果&#xff1a;门静脉淤血会同时导致脾静脉和肠系膜上静脉淤血&#xff0c;引发后续系列症状。 2. 脾大和脾功能亢进 00:46 …...

41道Django高频题整理(附答案背诵版)

解释一下 Django 和 Tornado 的关系&#xff1f; Django和Tornado都是Python的web框架&#xff0c;但它们的设计哲学和应用场景有所不同。 Django是一个高级的Python Web框架&#xff0c;鼓励快速开发和干净、实用的设计。它遵循MVC设计&#xff0c;并强调代码复用。Django有…...

PostgreSQL 与 SQL 基础:为 Fast API 打下数据基础

在构建任何动态、数据驱动的Web API时&#xff0c;一个稳定高效的数据存储方案是不可或缺的。对于使用Python FastAPI的开发者来说&#xff0c;深入理解关系型数据库的工作原理、掌握SQL这门与数据库“对话”的语言&#xff0c;以及学会如何在Python中操作数据库&#xff0c;是…...