STL排序向量查找小于或等于给定值的第一个元素

时间:2016-11-22 16:51:03

标签: c++ algorithm vector stl binary-search

我有pairs的向量。假设它是这样的:

vector<pair<int,int>> vec = { {1,12}, {1,5}, {1,6}, {1,9}, {3,9}, {3,11}, {3,13}, {3,4}, {5,9}, {5,91}, {13,8}, {16,8}, {20,8}, {20,81} };

pairs按第一个元素排序。

给定pair,我需要找到向量中最后一个pair的索引,其第一个元素小于或等于给定对的第一个元素。如果最后pair,其他对位于其左侧,并且第一个元素的值相同,我需要所有这些对中的第一个:

<4,10> => 4 (vec[4] is <3,9>, the elements with the largest first value less than or equal to 4 are those with first element as 3, and there are 4 pairs with a 3 in the first element, at indices 4-7, so return the first of those pairs)

<0,10> => -1, since no element exists to its right.

<1,6> => 0 (vec[0] is <1,12>. There is no pair whose first element is less than 1, and there are 4 pairs, including <1,6> whose first element is 1. So we need the first of these 4 pairs.)

<23,81> => 12 (vec[12] is <20,8>)

条件:我只需要使用标准算法,例如upper_boundbinary_searchlower_bound。我试过这个,但是它失败了:

vector<pair<int,int>> vec = { {1,12}, {1,5}, {1,6},{1,9}, {3,9}, {3,11}, {3,13}, {3,4}, {5,9}, {5,91}, {13,8}, {16,8}, {20,8}, {20,81} };

auto i = std::lower_bound(vec.begin(), vec.end(), make_pair<int,int>(4,10),
    [](const pair<int,int>& f1, const pair<int,int>& f2) { return f1.first < f2.first; });

cout << i-vec.begin();

2 个答案:

答案 0 :(得分:5)

既然你想要第一对,你可能想要结合下限和上限?

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

using namespace std;

int main()
{
    vector<pair <int,int> > vec = { {1,12}, {1,5}, {1,6}, {1,9}, {3,9}, {3,11}, {3,13}, {3,4}, {5,9}, {5,91}, {13,8}, {16,8}, {20,8}, {20,81} };

    auto u_it = std::upper_bound(vec.begin(), vec.end(), make_pair<int,int>(4, 10),
        [](const pair<int,int>& f1, const pair<int,int>& f2) { return f1.first < f2.first; });

    if(u_it == vec.begin())
        cout << "-1\n";

    auto l_it = std::lower_bound(vec.begin(), u_it, *prev(u_it),
        [](const pair<int,int>& f1, const pair<int,int>& f2) { return f1.first < f2.first; });

    cout << l_it - vec.begin() << "\n";
    return 0;

}

输出:

Georgioss-MacBook-Pro:~ gsamaras$ g++ -Wall -std=c++0x main.cpp 
Georgioss-MacBook-Pro:~ gsamaras$ ./a.out 
4

PS - 在WhozCraig评论后更新答案:

  

你想使用it = std::upper_bound(beg,end)来找到第一个严格更大的元素,如果它回答非开始,那么使用std::lower_bound(beg,it)来找到其值被拉的元素的最低匹配序数来自(it-1)

现在答案满足您提供的所有 测试用例(我在这里没有显示)。希望有所帮助! :)

附录:

参考std::lower_boundstd::upper_boundstd::prev。请注意std::lower_bound调用如何使用std::make_pair 而不使用初始化列表,以便让编译器发挥作用并解析deduce the type

答案 1 :(得分:0)

std::lower_bound返回第一个大于或等于给定值

你需要

  • +1std::lower_bound
  • 的输入
  • -1std::lower_bound
  • 的结果

找到值(或者你可以使用std::upper_bound

再次使用std::lower_bound找到合适的对

例如

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

int my_find(const vector<pair<int,int>>& vec, int value){
   auto comparer = [](const pair<int,int>& f1, int value) { return f1.first < value; };

   auto i = std::lower_bound(vec.begin(), vec.end(), value+1, comparer);
   if(i==vec.begin()){return -1;}

   i = std::lower_bound(vec.begin(), vec.end(), (i-1)->first, comparer);
   return i-vec.begin();
}

int main(){

   vector<pair<int,int>> vec = { {1,12}, {1,5}, {1,6},{1,9}, {3,9}, {3,11}, {3,13}, {3,4}, {5,9}, {5,91}, {13,8}, {16,8}, {20,8}, {20,81} };

   cout << my_find(vec,-1) << '\n';
   cout << my_find(vec,3) << '\n';
   cout << my_find(vec,10) << '\n';
   cout << my_find(vec,100) << '\n';
}

顺便说一下,您不需要pair提供lower_bound

如果您只使用lower_bound,则只需要一个比较器