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

6.二分算法

二分

二分算法,也称为二分查找或折半查找,是一种在有序数组中查找特定元素的高效算法。以下是 C++ 中二分算法的相关内容:

算法原理

  • 二分算法的基本思想是将有序数组分成两部分,然后将目标值与中间元素进行比较。如果目标值等于中间元素,则查找成功;如果目标值小于中间元素,则在数组的左半部分继续查找;如果目标值大于中间元素,则在数组的右半部分继续查找。重复这个过程,直到找到目标值或者确定目标值不存在于数组中。
  • 通过 不断折半缩小搜索范围 的查找方式,时间复杂度为 O(log n),需满足:
    1. 数据存储在 线性结构(如数组)
    2. 数据必须 有序(升序/降序)

代码实现

以下是一个使用 C++ 实现二分算法的示例代码:

#include <iostream>
#include <vector>

using namespace std;

// 二分查找函数
int binarySearch(vector<int>& nums, int target) {
    int left = 0;
    int right = nums.size() - 1;

    while (left <= right) {
        // 避免溢出
        int mid = left + (right - left) / 2;

        if (nums[mid] == target) {
            return mid;
        }
        else if (nums[mid] < target) {
            left = mid + 1;
        }
        else {
            right = mid - 1;
        }
    }

    // 目标值不存在于数组中
    return -1;
}

int main() {
    vector<int> nums = {1, 3, 5, 7, 9, 11, 13, 15, 17, 19};
    int target = 7;

    int result = binarySearch(nums, target);

    if (result!= -1) {
        cout << "目标值 " << target << " 在数组中的索引为:" << result << endl;
    }
    else {
        cout << "目标值 " << target << " 不存在于数组中。" << endl;
    }

    return 0;
}

复杂度分析

  • 时间复杂度:二分算法每次迭代都将搜索区间减半,因此时间复杂度为O(log n),其中 是n数组的长度。这使得二分算法在处理大规模数据时非常高效。
  • 空间复杂度:在上述代码中,除了输入的数组外,只使用了几个额外的变量,如leftrightmid,它们的数量不随输入规模增长,所以空间复杂度为O(1)。

应用场景

  • 数据查找:在有序数组或有序列表中快速查找特定元素,如在电话号码簿、字典等数据结构中查找特定的记录。
  • 求解方程:可以用于数值计算中求解方程的根。例如,对于一个单调递增或单调递减的函数,可以通过二分算法来逼近方程的解。
  • 优化问题:在一些优化问题中,二分算法可以用于搜索最优解的范围。例如,在寻找最小化或最大化某个目标函数的参数时,可以利用二分算法来缩小搜索空间。

注意事项

  • 二分算法要求数据必须是有序的。如果数据是无序的,需要先进行排序操作,这可能会增加额外的时间复杂度。
  • 在实现二分算法时,需要注意边界条件的处理,以确保算法的正确性和稳定性。

在库中

C++在STL库中已经封装好了二分算法,我们只需要引入调用即可。

<algorithm> 头文件中提供以下关键函数:

函数作用返回值
std::binary_search(beg, end, val)检查元素是否存在bool
std::lower_bound(beg, end, val)返回第一个 ≥val 的迭代器迭代器
std::upper_bound(beg, end, val)返回第一个 >val 的迭代器迭代器
#include <algorithm>
#include <vector>

int main() {
    std::vector<int> nums = {1, 3, 5, 7, 9};
    
    // 查找是否存在
    bool exists = std::binary_search(nums.begin(), nums.end(), 5); // true
    
    // 查找插入位置
    auto lower = std::lower_bound(nums.begin(), nums.end(), 6); // 指向7
    int pos = lower - nums.begin(); // 插入位置索引为3
    
    // 统计元素出现次数
    auto upper = std::upper_bound(nums.begin(), nums.end(), 5);
    int count = upper - lower; // 1次
}

http://www.kler.cn/a/527817.html

相关文章:

  • DeepSeek-R1 论文解读 —— 强化学习大语言模型新时代来临?
  • LabVIEW温度修正部件测试系统
  • AJAX笔记入门篇
  • docker配置mysql并使用mysql connector cpp编程
  • Chrome浏览器编译系统研究与优化分析
  • 百度热力图数据获取,原理,处理及论文应用5
  • 舵机型号与识别
  • Go学习:Go语言中if、switch、for语句与其他编程语言中相应语句的格式区别
  • 三天急速通关JavaWeb基础知识:Day 2 前端基础知识(计划有变,前端工程化部分暂时搁置)
  • Vue.js 生命周期钩子在 Composition API 中的应用
  • 《解锁DeepSeek本地部署:开启你的专属AI之旅》
  • 绝对值线性化
  • 【python】python基于机器学习与数据分析的手机特性关联与分类预测(源码+数据集)【独一无二】
  • Flink2支持提交StreamGraph到Flink集群
  • 使用 cmake
  • 书生大模型实战营6
  • 动态规划每日一练(四)
  • 算法11(力扣496)-下一个更大元素I
  • MATLAB-Simulink并行仿真示例
  • 前端 Vue 性能提升策略
  • DeepLens是一个用于计算镜头设计的可微光线追踪器
  • Redis代金卷(优惠卷)秒杀案例-多应用版
  • JVM的GC详解
  • 六. Redis当中的“发布” 和 “订阅” 的详细讲解说明(图文并茂)
  • Fiddler(一) - Fiddler简介_fiddler软件
  • Spring--Bean的生命周期和循环依赖