您的位置:首页 > 健康 > 养生 > 网页设计师岗位介绍_中天建设集团有限公司西南分公司_济南seo整站优化招商电话_杭州推广公司

网页设计师岗位介绍_中天建设集团有限公司西南分公司_济南seo整站优化招商电话_杭州推广公司

2025/3/31 18:56:20 来源:https://blog.csdn.net/m0_74878305/article/details/146285534  浏览:    关键词:网页设计师岗位介绍_中天建设集团有限公司西南分公司_济南seo整站优化招商电话_杭州推广公司
网页设计师岗位介绍_中天建设集团有限公司西南分公司_济南seo整站优化招商电话_杭州推广公司

整数二分算法模板 —— 模板题 AcWing 789. 数的范围
bool check(int x) {/* ... */} // 检查x是否满足某种性质

// 区间[l, r]被划分成[l, mid]和[mid + 1, r]时使用:
int left_search(int l, int r)
{
    while (l < r)
    {
        int mid = l + r >> 1;
        if (check(mid)) r = mid;    // check()判断mid是否满足某种性质
        else l = mid + 1;
    }
    return l;
}
// 区间[l, r]被划分成[l, mid - 1]和[mid, r]时使用:
int right_search(int l, int r)
{
    while (l < r)
    {
        int mid = l + r + 1 >> 1;
        if
(check(mid)) l = mid;
        else r = mid - 1;

注意:有+就有-
    }
    return l;
}

二分法(Binary Search)详解

二分法(Binary Search)是一种经典的 分治算法,常用于在 已排序的数组区间 中查找目标值。其核心思想是通过不断将搜索区间对半分,缩小查找范围,从而 高效 地找到目标元素。二分法的时间复杂度是 O(log n),因此在处理大规模数据时非常高效。

基本思想

二分查找的核心思路是:

  1. 将待查找的区间分成两部分,根据中间元素与目标值的比较结果决定下一步搜索的区间。
  2. 继续在新的一半区间内查找,不断缩小查找的范围,直到找到目标元素,或确认目标元素不在数组中。
基本步骤
  1. 初始化区间:设定两个边界,通常是 左边界 l右边界 r,表示当前查找的范围。
  2. 计算中间位置 mid:每次计算中间位置 mid = (l + r) / 2(或者使用 mid = l + (r - l) / 2 来防止溢出)。
  3. 比较中间值与目标值
    • 如果中间值等于目标值,则 找到了目标
    • 如果中间值大于目标值,则目标值可能在中间值的左侧,因此 将右边界 r 移动到 mid - 1
    • 如果中间值小于目标值,则目标值可能在中间值的右侧,因此 将左边界 l 移动到 mid + 1
  4. 停止条件:当 左边界 l 不再小于右边界 r,说明找到了目标,或者目标不在数组中。

例:假设数组 a = {1, 2, 2, 3, 3, 3, 4, 5, 5},并查询 x = 3,左边界右边界的位置

  1. 查找左边界

    • 使用 searchleft(0, 8, 3),通过二分查找,返回第一个 3 出现的位置,结果是 3
  2. 查找右边界

    • 使用 searchright(0, 8, 3),通过二分查找,返回最后一个 3 出现的位置,结果是 5
  3. 输出

#include <algorithm>
#include <iostream>
using namespace std;const int N = 1e5 + 10; // 定义数组大小的上限
int a[N]; // 数组,用来存储输入的已排序整数// 左边界
int searchleft(int l, int r, int x) {while (l < r) {  // 当左右边界还未收敛时int mid = (r + l) >> 1;  // 计算中间位置if (a[mid] >= x) r = mid;  // 如果中间值大于等于 x,则右边界收缩else l = mid + 1;  // 如果中间值小于 x,则左边界收缩}return l;  // 返回左边界位置,表示第一个大于等于 x 的位置
}// 右边界
int searchright(int l, int r, int x) {while (l < r) {  // 当左右边界还未收敛时int mid = (l + r + 1) >> 1;  // 计算中间位置,偏向右侧if (a[mid] <= x) l = mid;  // 如果中间值小于等于 x,则左边界收缩else r = mid - 1;  // 如果中间值大于 x,则右边界收缩}return r;  // 返回右边界位置,表示最后一个小于等于 x 的位置
}int main() {int n, q;  // n 为数组的长度,q 为查询次数cin >> n >> q;  // 输入数组长度和查询次数for (int i = 0; i < n; i++) cin >> a[i];  // 输入已排序数组while (q--) {  // 循环处理每一个查询int x;  // 当前查询的目标数字cin >> x;  // 输入要查询的数字 x// 查找第一个大于等于 x 的位置,使用左边界二分查找int l = searchleft(0, n - 1, x);// 如果 l 指向的不是 x,说明数组中没有 xif (a[l] != x) {cout << "-1 -1" << endl;  // 输出 -1 -1,表示 x 不在数组中} else {// 查找最后一个小于等于 x 的位置,使用右边界二分查找int r = searchright(0, n - 1, x);// 输出左边界和右边界,即 x 的第一次和最后一次出现的位置cout << l << " " << r << endl;}}return 0;  // 返回 0,程序正常结束
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com