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

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

1.1 题目含义

给定一个升序排列的整数数组 nums 和一个目标值 target,写一个函数来搜索 nums 中的 target,如果目标值存在于数组中,则返回它的索引;否则返回 -1。你必须使用二分查找算法来解决这个问题。

二分查找算法是一种在有序数组中查找某一特定元素的搜索算法。搜索过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜索过程结束;如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较。如果在某一步骤数组为空,则代表找不到。

1.2 示例

示例 1:
输入:

  • nums = [-1, 0, 3, 5, 9, 12]
  • target = 9

输出:

  • 4

说明:

  • 9 存在于 nums 中,且其索引为 4。

示例 2:
输入:

  • nums = [-1, 0, 3, 5, 9, 12]
  • target = 2

输出:

  • -1

说明:

  • 2 不存在于 nums 中,返回 -1。

示例 3:
输入:

  • nums = []
  • target = 0

输出:

  • -1

说明:

  • nums 为空,0 不存在于 nums 中,返回 -1。

2 解题思路

2.1 循环遍历实现

(1)初始化指针:

  • 设定三个指针,start 指向数组的开始位置,end 指向数组的结束位置,mid 用于计算当前查找区间的中间位置。

(2)计算中间位置:

  • 根据 start 和 end 的位置,计算出当前查找区间的中间位置 mid。这里要注意防止整数溢出,所以可以使用 (start + end) / 2 的方式来计算。

(3)比较与目标值:

  • 将 mid 位置的元素与目标值进行比较。

(4)调整查找区间:

  • 如果 mid 位置的元素等于目标值,则查找成功,直接返回 mid。
  • 如果 mid 位置的元素大于目标值,说明目标值(如果存在)只可能出现在 mid 的左侧,因此更新 end 为 mid - 1。
  • 如果 mid 位置的元素小于目标值,说明目标值(如果存在)只可能出现在 mid 的右侧,因此更新 start 为 mid + 1。

(5)循环判断:

  • 重复步骤 2 至步骤 4,直到 start 大于 end,这意味着整个查找区间已经被遍历完,且没有找到目标值。

(6)返回结果:

  • 如果循环结束仍然没有找到目标值,则返回 -1 表示查找失败。

2.2 递归实现

使用递归实现二分查找的解题思路如下:

首先,需要明确递归的基本思想:将问题分解为更小的子问题,直到子问题可以直接解决。在二分查找中,每次都将搜索范围划分为两部分,并递归地在其中一部分中继续查找,直到找到目标值或确定目标值不存在。

(1)定义递归函数:

  • 定义一个递归函数,该函数接收一个有序数组、目标值、当前搜索范围的起始位置 start 和结束位置 end 作为参数。

(2)递归终止条件:

  • 当 start 大于 end 时,表示当前搜索范围为空,即目标值不在数组中,递归终止,返回 -1。

(3)计算中间位置:

  • 在递归函数中,计算当前搜索范围的中间位置 mid。

(4)比较与目标值:

  • 将 mid 位置的元素与目标值进行比较。

(5)递归调用:

  • 如果 mid 位置的元素等于目标值,则递归终止,返回 mid。
  • 如果 mid 位置的元素大于目标值,说明目标值(如果存在)只可能出现在 mid 的左侧,因此递归调用函数,传入新的搜索范围(start,mid - 1)。
  • 如果 mid 位置的元素小于目标值,说明目标值(如果存在)只可能出现在 mid 的右侧,因此递归调用函数,传入新的搜索范围(mid + 1,end)。

(6)返回结果:

  • 递归调用的结果即为最终的查找结果,将其返回。

这个递归过程会一直进行下去,直到找到目标值或确定目标值不在数组中。递归实现方式使得代码更加简洁和清晰,但需要注意递归深度的问题,避免因为递归过深而导致栈溢出。在实际应用中,如果数组规模很大,建议使用循环遍历实现来避免这个问题。

3 算法实现代码

3.1 循环遍历实现

如下为算法实现代码:

#include <iostream>  
#include <string>  
#include <vector>  class Solution
{
public:int binarySearch(std::vector<int>& nums, int target) {int start = 0;int end = nums.size() - 1;while (start <= end) {int mid = start + (end - start) / 2; // 防止溢出  if (nums[mid] == target) {// 找到目标值,返回其索引  return mid;}else if (nums[mid] < target) {// 目标值在mid右侧,更新start  start = mid + 1;}else {// 目标值在mid左侧,更新end  end = mid - 1;}}// 没有找到目标值  return -1;}
};

这段代码中定义了一个名为 binarySearch 的成员函数,它接受一个整数向量 nums 和一个目标值 target 作为参数。函数内部使用 start 和 end 变量来追踪当前搜索范围的左右边界,并通过计算中间位置 mid 来确定接下来搜索哪一部分。根据 mid 位置的元素与目标值的比较结果,更新 start 或 end 的值来缩小搜索范围。当 start 大于 end 时,表示搜索区间已被遍历完,此时返回 -1 表示未找到目标值。如果找到目标值,则返回其索引。

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

int main() 
{Solution s;std::vector<int> nums = { -1, 0, 3, 5, 9, 12 };int target = 9;int result = s.binarySearch(nums, target);if (result != -1) {std::cout << "Target found at index: " << result << std::endl;}else {std::cout << "Target not found in the array." << std::endl;}return 0;
}

上面代码的输出为:

Target found at index: 4

3.2 递归实现

如下为算法实现代码:

#include <iostream>  
#include <string>  
#include <vector>  class Solution
{
public:int binarySearch(std::vector<int>& nums, int target) {		return binarySearchRecursive(nums, target, 0, nums.size() - 1);}private:int binarySearchRecursive(const std::vector<int>& nums, int target, int start, int end) {// 递归终止条件  if (start > end) {return -1; // 目标值不在数组中  }int mid = start + (end - start) / 2; // 防止溢出  // 检查是否找到目标值  if (nums[mid] == target) {return mid;}// 递归调用:目标值在左半部分  if (nums[mid] > target) {return binarySearchRecursive(nums, target, start, mid - 1);}// 递归调用:目标值在右半部分  return binarySearchRecursive(nums, target, mid + 1, end);}
};

这段代码中定义了一个名为 binarySearchRecursive 的私有递归成员函数,它接受一个整数向量 nums、一个目标值 target、以及当前搜索范围的起始位置 start 和结束位置 end 作为参数。
函数内部首先检查递归终止条件,即 start 是否大于 end,如果是,则返回 -1 表示未找到目标值。接着,计算中间位置 mid,然后与目标值进行比较。如果 mid 位置的元素等于目标值,则直接返回 mid。否则,根据比较结果递归地在左半部分或右半部分继续查找。递归调用会一直进行下去,直到找到目标值或搜索范围为空。

4 测试用例

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

(1)基础测试用例
输入:数组 [-1, 0, 3, 5, 9, 12],目标值 9
输出:4
说明:目标值 9 存在于数组中,位于索引 4 的位置。

(2)目标值不存在于数组中
输入:数组 [-1, 0, 3, 5, 9, 12],目标值 2
输出:-1
说明:目标值 2 不存在于数组中。

(3)目标值位于数组开头
输入:数组 [-1, 0, 3, 5, 9, 12],目标值 -1
输出:0
说明:目标值 -1 位于数组的开头,即索引 0 的位置。

(4)目标值位于数组末尾
输入:数组 [-1, 0, 3, 5, 9, 12],目标值 12
输出:5
说明:目标值 12 位于数组的末尾,即索引 5 的位置。

(5)目标值位于数组中间
输入:数组 [-1, 0, 3, 5, 9, 12],目标值 3
输出:2
说明:目标值 3 位于数组的中间位置,即索引 2 的位置。

(6)空数组
输入:数组 [],目标值 9
输出:-1
说明:空数组不包含任何元素,因此无法找到目标值。

(7)数组只有一个元素
输入:数组 [9],目标值 9
输出:0
说明:数组只有一个元素,且该元素就是目标值,位于索引 0 的位置。

(8)数组中存在多个相同的目标值
输入:数组 [1, 2, 3, 3, 4, 5],目标值 3
输出:2 或 3
说明:数组中存在多个目标值 3,返回任意一个目标值的索引都是正确的。这里可以返回 2 或 3。

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

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

相关文章

Cocos2dx-lua ScrollView[二]进阶篇

一.概述 本文缩写说明:sv = ScrollView, item代表ScrollView的一个子节点 如果对sv熟系程度还不够,请阅读基础篇: Cocos2dx-lua ScrollView[一]基础篇-CSDN博客 本文介绍sv的一种封装类库,来实现快速创建sv,有如下几个优点: 1.item的位置通过参数控制,提高开发效率…

使用Java自带的VisualVM监控远程服务器部署在Docker容器中的Java项目并使用Mat在线工具排查服务器内存泄露或内存溢出的原因

事情是这样的&#xff0c;我们项目最近应业主的要求迁移到了新的服务器&#xff0c;起初一切正常&#xff0c;部署、上线、测试都没有问题&#xff0c;项目大概运行了一周的工作日时间都没出现问题&#xff0c;直到周六那天&#xff0c;项目经理打电话过来说服务器崩了&#xf…

鼠标不动了怎么办?4招帮你解决问题!

“我在使用鼠标时&#xff0c;用着用着鼠标就动不了了&#xff0c;这是为什么呢&#xff1f;怎么才能让鼠标恢复正常呢&#xff1f;” 鼠标作为电脑使用中最常用的输入设备之一&#xff0c;其正常运行对于我们的工作效率至关重要。然而&#xff0c;有时我们可能会遇到鼠标突然不…

深入学习React开发:从基础到实战

&#x1f482; 个人网站:【 海拥】【神级代码资源网站】【办公神器】&#x1f91f; 基于Web端打造的&#xff1a;&#x1f449;轻量化工具创作平台&#x1f485; 想寻找共同学习交流的小伙伴&#xff0c;请点击【全栈技术交流群】 引言 React是一款流行的JavaScript库&#xf…

C#重新认识笔记_ FixUpdate + Update

C#重新认识笔记_ FixUpdate Update Update: 刷新频率不一致,非物理对象的移动&#xff0c;简单的刷新可用&#xff0c; FixedUpdate: 刷新频率一致,按照固定频率刷新&#xff0c;一般调用FixedUpdate之后&#xff0c;会立即进入必要的物理计算中,因此&#xff0c;任何影响刚…

Union和union导致的数据不一致

平时工作中经常用到union&#xff0c;可以自带去重的操作&#xff0c;今天有个汇总的SQL也用了这个&#xff0c;需求是统计多张表的余额字段&#xff0c;看着就很简单union再sum或者sum再union。 第一种每张表先汇总&#xff0c;使用 UNION ALL 合并后最外层再汇总 SELECT SUM(…

【CSP试题回顾】201803-1-跳一跳

CSP-201803-1-跳一跳 解题代码 #include <iostream> using namespace std;int score, s, last_s -1;int main() {while (true){cin >> s;if (s 0) break;else if (s 1) {score s;last_s s;}else if (s 2) {if (last_s>2){score last_s;last_s 2;}else…

Python 界面逻辑分离示例

本示例使用的发卡设备&#xff1a;https://item.taobao.com/item.htm?id615391857885&spma1z10.5-c.w4002-21818769070.11.6cc85700Robi3x 一、Python 安装PyQt5&#xff0c;运行 Qt Designer 新建窗体文件&#xff0c;在窗体中拖放控件 完成界面设计&#xff0c;保存为…

克隆图00

题目链接 克隆图 题目描述 注意点 节点数不超过100每个节点值 Node.val 都是唯一的&#xff0c;1 < Node.val < 100无向图是一个简单图&#xff0c;这意味着图中没有重复的边&#xff0c;也没有自环图是连通图&#xff0c;可以从给定节点访问到所有节点 解答思路 本…

活动图高阶讲解-03

1 00:00:00,000 --> 00:00:06,260 刚才我们讲了活动图的历史 2 00:00:06,260 --> 00:00:11,460 那我们来看这个活动图 3 00:00:11,460 --> 00:00:15,260 如果用来建模的话怎么用 4 00:00:15,260 --> 00:00:20,100 按照我们前面讲的软件方法的工作流 5 00:00:20…

【网络安全】手机不幸被远程监控,该如何破解,如何预防?

手机如果不幸被远程监控了&#xff0c;用三招就可以轻松破解&#xff0c;再用三招可以防范于未然。 三招可破解可解除手机被远程监控 1、恢复出厂设置 这一招是手机解决软件故障和系统故障的终极大招。只要点了恢复出厂设置&#xff0c;你手机里后装的各种APP全部将灰飞烟灭…

STM32中断和外部中断

NVIC&#xff1a;嵌套中断向量控制器&#xff1a;用于统一分配中断优先级和管理中断 响应式优先级&#xff1a;也可以称为插队式优先级哪个优先级高优先处理哪个 抢占式优先级&#xff1a;优先级高的可以优先被处理&#xff0c;相当于CPU可以暂时中断当前处理的程序&#xff0c…

深入理解对话框管理器:自定义 TAB 按键行为

有人想开发这样一个功能,说界面上有一个多行文本编辑框,他希望用户按下 TAB 按键后可以将输入焦点导航至其他控件,而不是在文本框里默认地输入一个 TAB 字符。 如果是你,你觉得应该怎样做呢? 他琢磨了一下,觉得应该使用子类化的方式来实现这项功能,代码如下: >&g…

报文解析模块模型

一、引言 报文解析模块是信息系统中关键的一环&#xff0c;它负责接收、验证、解码、提取、处理报文数据&#xff0c;并输出结果。一个高效且稳定的报文解析模块对于确保数据传输的准确性、及时性以及系统的可靠性至关重要。本文档将详细介绍报文解析模块的主要组成部分及其功…

opencv install

安装 opencv 版本为 4.2 一、前置条件 1. gcc安装 yum install gcc2. 安装cmake 注意安装 opencv-4.2 版本&#xff0c;需要 cmake-3.5.1 及其以上&#xff0c;安装脚本如下&#xff1a; #!/bin/bash# 设置下载和安装目录 DOWNLOAD_DIR"/tmp/cmake_download" IN…

提升大模型解释性:新型解释性方法的研究与实践

提升大模型解释性&#xff1a;新型解释性方法的研究与实践 摘要&#xff1a; 随着深度学习技术的快速发展&#xff0c;大模型在各个领域取得了显著成果。然而&#xff0c;这些模型往往缺乏解释性&#xff0c;导致其决策过程难以理解。本文旨在探讨新型解释性方法的研究与实践…

Python算法(列表排序)

一。冒泡排序&#xff1a; 列表每两个相邻的数&#xff0c;如果前面比后面大&#xff0c;则交换这两个数 一趟排序完成后&#xff0c;则无序区减少一个数&#xff0c;有序区增加一个数 时间复杂度&#xff1a;O(n*n) 优化后&#xff1a;已经排序好后立马停止&#xff0c;加快…

【力扣 - 合并区间】

题目描述 以数组 intervals 表示若干个区间的集合&#xff0c;其中单个区间为 intervals[i] [start_i, end_i] 。请你合并所有重叠的区间&#xff0c;并返回 一个不重叠的区间数组&#xff0c;该数组需恰好覆盖输入中的所有区间 。 示例 1&#xff1a; 输入&#xff1a;int…

Github 2024-03-14 开源项目日报 Top10

根据Github Trendings的统计,今日(2024-03-14统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Python项目4Rust项目2Go项目2TypeScript项目2非开发语言项目1C++项目1免费API集合 创建周期:2900 天开发语言:Python协议类型:MIT LicenseSt…

环形缓冲区在stm32上的使用

目录 环形缓冲区在stm32上的使用前言实验目的环形缓冲区的定义和初始化写入数据到环形缓冲区从环形缓冲区读取数据实验结果本文中的实践工程 环形缓冲区在stm32上的使用 本文目标&#xff1a;环形缓冲区在stm32上的使用 按照本文的描述&#xff0c;应该可以跑通实验并举一反三…