【问题标题】:Find largest element smaller than current with STL使用 STL 查找小于当前元素的最大元素
【发布时间】:2015-03-11 14:44:35
【问题描述】:

在排序容器中是否有一个单行来查找小于某个元素 x 的最大元素?我基本上对任何可以给我一个指向小于 x 的最大元素的迭代器的代码感兴趣。

我知道如何自己编写代码,但希望有一个库函数...

编辑:也许我应该在这里澄清一下,我想到的我自己编写代码的版本是基于二进制搜索的,因此在 O(log n) 时间内运行。我需要为包含数百万个元素的列表计算此值。

【问题讨论】:

  • std::max_element(container.begin(), std::lower_bound(container.begin(), container.end(), x));
  • 这是 O(log n) 复杂度,任何基于二进制搜索的方法都可以提供吗? (即我自己编写的版本,因为容器已排序)
  • 这会更快,即使不是那么优雅:auto bound = std::lower_bound(container.begin(), container.end()); if (bound != container.begin()) --bound; else bound = container.end();} 基本上,找到一个元素的位置 x 或更大,降低一个位置(注意边缘条件) .这只会执行一次二分搜索。
  • @JT1 用于排序容器,是的,提供的解决方案是 O(log(n))

标签: c++11 stl


【解决方案1】:

由于您的容器已排序,因此您可以在以大于最大值的第一个元素结尾的范围上使用 std::max_element,使用带有 lambda 的 std::find_ifstd::lower_bound 来获取此范围:

int main()
{
    std::set<int> s{ 3, 1, -14, 1, 5, 9 }; 
    std::set<int>::iterator result;

    int max_value = 6;
    result = std::max_element(std::begin(s), std::find_if(std::begin(s), std::end(s), [&](int i) { return i >= max_value; } ) );
    std::cout << "max element is: " << *result;
}

输出:

最大元素为:5

Live Demo

或者std::lower_bound

int main()
{
    std::set<int> s{ 3, 1, -14, 1, 5, 9 }; 
    std::set<int>::iterator result;

    int max_value = 6;
    result = std::max_element(std::begin(s), std::lower_bound(std::begin(s), std::end(s), max_value)) ;
    std::cout << "max element is: " << *result;
}

Live Demo

【讨论】:

  • 这些 sn-ps 假设总有一个元素小于 max_value。否则返回容器中的最小元素:max_value = -20 // =&gt; result -14
【解决方案2】:

你可以使用

lower_bound(container.begin(), container.end(), currentElement);

现在,如果它与container.begin() 不同,那么有一个元素比您当前的元素小,只需减去一个即可。如果你确定总会有这样的元素,那就去做吧

lower_bound(container.begin(), container.end(), currentElement) - 1;

编辑:当然,我假设您的迭代器是双向的。

【讨论】:

    【解决方案3】:

    假设您的数据在整数集合s 中,您可以找到小于 x 的最大元素,如下所示:

    auto it = s.lower_bound( x ); // s.lower_bound has a complexity of O(logn)
    if( it == s.begin() )
    {
        std::cout << "No element found" << "\n";
    }
    else
    {
        --it;
        std::cout << *it << "\n";
    }
    

    lower_bound 本质上返回一个迭代器it 指向最小元素&gt;= x。因此,它只是先前的指针--it 将指向最大的元素&lt; x。这种方法的复杂性是O(log n)

    【讨论】:

      【解决方案4】:

      prev()lower_bound() 结合使用

      • mycontainer.lower_bound(int_val) 将迭代器返回到等于或大于 int_val 的数字

      • *prev(mycontainer.lower_bound(int_val)) 返回容器中 int_val 之前的值

      作为防御性检查,首先验证它不在容器的开头:

      int result = -1, target = 15;
      set<int> _container;
      auto _iterator = _container.lower_bound(target);
      if(_iterator != _container.begin())
         result = *std::prev(_iterator);
      

      【讨论】:

        猜你喜欢
        • 2021-03-24
        • 1970-01-01
        • 2014-07-21
        • 2014-11-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-05-08
        • 1970-01-01
        相关资源
        最近更新 更多