【问题标题】:C++ lower_bound() to search for the closest element to a target valueC++ lower_bound() 搜索最接近目标值的元素
【发布时间】:2020-06-06 11:26:01
【问题描述】:

假设我有一个vector,它的元素是int 类型。如何优雅地使用std::lower_bound() 来寻找最接近目标值的元素?

我写的代码如下图:

#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> vec {3,4,5,10};
    int target = 6;

    auto found {
        lower_bound(
            vec.begin(),
            vec.end(),
            target,
            [=] (int ele1, int ele2) {
                return (abs(ele1 - target) > abs(ele2 - target));
            }
        )
    };

    cout << (found-vec.begin()) << endl;

    return 0;
}

它返回4的索引,这意味着found = vec.end()。相反,我想获得2 的索引。我哪里搞砸了?

【问题讨论】:

  • lower_bound 要求被搜索容器的内容根据比较函数排序,在这种情况下不正确,因为这样显示的代码是未定义的行为。
  • 如果vec 是有序且大的,使用区间二分法、牛顿法或(我最喜欢在收敛性和保证方面)Ridder 法可能有用。
  • 为什么要使用lower_bound?它似乎不是这项工作的好工具。

标签: c++ binary-search lower-bound


【解决方案1】:

您在lower_bound 中使用的谓词与用于vec 排序的谓词不同。所以你的代码 sn-p 有未定义的行为。

您仍然可以使用lower_bound 来简单地查找target

auto attempt = lower_bound(vec.begin(), vec.end(), target);

现在您实际查找的迭代器将是返回的迭代器,或者是下一个元素的迭代器:

auto found = attempt == vec.end() ? 
             vec.end() - 1 :   // last element is closest
             attempt == vec.begin() ? 
             vec.begin() :  // first element is closest
             abs(*attempt - target) < abs(*(attempt - 1) - target) ? 
             // somewhere in the middle, then the previous element could be closer
             attempt : attempt - 1;   

这假定 vec 不为空,因此您可能还需要进行该检查。

这是demo

【讨论】:

  • 我用 OP 的数据测试了这个解决方案,它说 10 是最接近的数字。 (found-vec.begin() 为 3,*found 为 10。)我可能遗漏了一些东西,但这似乎不对。
  • @DennisSparrow 已编辑,我需要先检查迭代器。谢谢指正。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-11-14
  • 1970-01-01
  • 2017-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多