如何将 lower_bound 应用于一系列未排序的向量元素?

Posted

技术标签:

【中文标题】如何将 lower_bound 应用于一系列未排序的向量元素?【英文标题】:How do i apply lower_bound to a range of unsorted vector elements? 【发布时间】:2020-10-01 06:54:49 【问题描述】:

我有一个整数向量scores = 10, 23, 29, 77, 8, 43, 56, 3 连同一个号码predict = 42 start index = 2

我正在搜索两个数字,(大于和小于)接近predict = 42,在start index = 2end index = 7 的范围内

scores = 10, 23, 29, 77, 8, 43, 56, 3 (仅在 i=2 到 i=7 范围内搜索)

所以,29 比 predict=42 少一点

而且,43 比预测的 42 多一点

我如何获得这些数字?

示例代码:

#include <algorithm>
#include <iostream>
#include <vector>

using namespace std;

int main() 
    vector<int> scores = 10, 23, 29, 77, 8, 43, 56, 3; //Unsorted
    int predict = 42;
    int startFromIndex = 2;
    
    int littleLessThanPredict; // = 29
    int littleMoreThanPredict; // = 43
    
    //lower_bound
    //upper_bound
    
    return 0;

鉴于这种情况,

    如何在未排序的范围内使用std::lower_boundstd::upper_bound 函数? 如何临时对向量的一部分进行排序并应用我的自定义函数? 有没有办法结合std::min_elementstd::lower_bound函数来获得想要的结果?

【问题讨论】:

也许任务是让你自己想出一个算法?任务的要求和限制是什么?你从哪里得到的任务?你有没有和你的教授/老师/助教谈过这个(如果是学校作业)? 不是学校作业,它是一个控制台/文本游戏,而且,我正在尝试在其中一个步骤中实现此功能。我无法弄清楚 lambda 函数或异地排序算法的语法 我不明白你为什么需要lower/upper_bound。你不能只 for 循环从start index 开始并以end index 结束,如果你发现一个低于predict 的数字,你把它保存在littleLessThanPredict,如果它更大,你把它保存在littleMoreThanPredict。然后继续,如果你找到一个大于littleLessThanPredict但小于predict的数字,你更新littleLessThanPredict,如果你找到一个小于littleMoreThanPredict但大于predict的数字,你更新littleMoreThanPredict。跨度> 如果对分数进行了排序,lower_bound(scores.begin(), scores.end(), 42) 将返回一个指向 43 而不是 29 的迭代器 【参考方案1】:

如何在未排序的范围内使用 std::lower_bound 和 std::upper_bound 函数?

不,他们希望根据 value 对范围进行分区(所有小于 value 的条目必须在所有大于的条目之前)。 https://en.cppreference.com/w/cpp/algorithm/lower_bound

如何临时对向量的一部分进行排序并应用我的自定义函数?

如果您正在处理数字,也许最​​简单的方法是创建向量的副本并对其进行排序。这是 O(NlogN) 复杂度。

您也可以通过自己实现 lower_bound 来获得良好的性能(这将是 O(N))。

经验法则:如果您的数组通常很短(

有没有办法结合 std::min_element 和 std::lower_bound 函数来获得想要的结果?

不是真的。

【讨论】:

如果它是一个非常大的数组?我在这里寻找性能 @PersistentCache 在这种情况下,您需要自己实现 lower_bound 。这是一个 for 循环,您可以在其中查找大于目标值的最小元素。 @PersistentCache “非常大”是相对的。你谈论成千上万的元素吗?几万?数十万?对于数以千计的元素,现代计算机的速度足够快,可以处理甚至相当无效的算法。更不用说对于主机游戏,大部分时间都是程序处于空闲状态并等待用户输入。 @PersistentCache 分析您的代码也是一个好习惯。与从中获得最佳性能相比,从长远来看,可能还有其他热点会产生更大的影响。 理想情况下,15,000 个元素的向量大小应该可以。【参考方案2】:

为什么需要对数组进行排序?这将给出 O(N.ln(N)) 算法复杂度。

您可以在 O(N) 中结合未排序数组中的上限和下限研究来执行您的算法:

#include <algorithm>
#include <iostream>
#include <vector>
#include <climits>

using namespace std;

pair<int, int> nearestNumbers(const vector<int> &scores, int predict, int start) 
    int nearestLower = INT_MIN;
    int nearestUpper = INT_MAX;

    for (size_t i = start; i < scores.size(); i++) 
        int value = scores[i];
        if (value <= predict && value > nearestLower)
            nearestLower = value;
        else if (value >= predict && value < nearestUpper)
            nearestUpper = value;
    

    return pair<int, int>(nearestLower, nearestUpper);


int main() 
    vector<int> scores = 10, 23, 29, 77, 8, 43, 56, 3;
    int predict = 42;
    int start = 2;

    pair<int, int> results = nearestNumbers(scores, predict, start);
    cout << results.first << " " << results.second;

    return 0;

【讨论】:

【参考方案3】:

如果分数数组很小(对于某些未指定的“小”值),则无需对分数进行排序。

如果我没有正确阅读问题,您正在寻找小于predict 的最大值和大于predict 的最小值。那就这样做吧:

int lower = INT_MAX;
int upper = INT_MIN;
for (int i = start; i <= end; ++i) 
    if (scores[i] < predict)
        lower = std::max(lower, scores[i]);
    else
        upper = std::min(upper, scores[i]);

请注意,如果其中一个分数等于predict,则此代码将该值放入upper。如果这不是您想要的,则需要相应地调整代码。

【讨论】:

以上是关于如何将 lower_bound 应用于一系列未排序的向量元素?的主要内容,如果未能解决你的问题,请参考以下文章

将时间高斯滤波器应用于一系列图像

如何在向量向量上使用lower_bound?

二分检索函数lower_bound()和upper_bound()

lower_bound()函数使用

VBA 排序代码仅适用于一张纸,但不适用于多张

有关lower_bound()函数的使用