我有一个排序的整数元素向量。下面给出一个例子:
vector<int> A ={3,4,5,9,20,71,89,92,100,103,109,110,121,172,189,194,198};
现在给出以下&#34; start&#34;和&#34;结束&#34;范围我想找出向量A的哪些元素属于开始和结束范围。
int startA=4; int endA=8;
int startB=20; int endB=99;
int startA=120; int endC=195;
例如,
elements lying in range startA and startB are: {4,5}
elements lying in range startA and startB are: {20,71,89,92}
elements lying in range startC and startC are: {121,172,189,194}
这样做的一种方法是迭代&#34; A&#34;并检查它们是否位于指定范围之间。是否有其他更有效的方法来找出满足给定范围的向量中的元素
答案 0 :(得分:5)
这样做的一种方法是迭代&#34; A&#34;并检查它们是否位于指定范围之间。是否有其他更有效的方法来找出满足给定范围的向量中的元素
如果对矢量进行了排序,正如您所示,您可以使用二进制搜索来定位元素的索引,该索引高于范围的较低值和低于较高值的元素的索引范围。
这将使您的搜索O(log(N))。
您可以使用std::lower_bound
和std::upper_bound
,这需要对容器进行部分订购,这在您的情况下是正确的。
如果矢量未排序,则可以进行线性迭代。
答案 1 :(得分:5)
如果对矢量进行了排序,那么您需要做的就是使用专用函数来查找起始范围迭代器和结束范围迭代器 - std::lower_bound
和std::upper_bound
。例如:
#include <vector>
#include <algorithm>
#include <iostream>
int main() {
std::vector<int> A ={3,4,5,9,20,71,89,92,100,103,109,110,121,172,189,194,198};
auto start = std::lower_bound(A.begin(), A.end(), 4);
auto end = std::upper_bound(A.begin(), A.end(), 8);
for (auto it = start; it != end; it++) {
std::cout << *it << " ";
}
std::cout << std::endl;
}
//or the C++1z version (works in VS2015u3)
int main() {
std::vector<int> A ={3,4,5,9,20,71,89,92,100,103,109,110,121,172,189,194,198};
std::copy(std::lower_bound(A.begin(), A.end(), 4),
std::upper_bound(A.begin(), A.end(), 8),
std::ostream_iterator<int>(cout, " "));
std::cout << std::endl;
}
但这仅适用于startX <= endX
,因此您可能希望在使用任意数字运行之前测试适当的条件...
使用std::lower_bound
和std::upper_bound
搜索绑定的迭代器将花费O(log(N))
但是必须说明的是,在平均情况下迭代元素范围是O(N)
和范围可能包含载体中的所有元素......
答案 2 :(得分:2)
我能想到的最好的方法是两次应用修改的二进制搜索并在向量arr中找到两个索引,然后打印此范围之间的所有项目。时间复杂度为O(log n)。 二进制搜索的修改形式如下所示:( PS用于数组,也适用于向量):
int binary_search(int *arr,int start,int end,int key)
{
if(start==end)
{
if(arr[start]==key){return start+1;}
else if(arr[start]>key&&arr[start-1]<=key){return start;}
else return 0;
}
int mid=(start+end)/2;
if(arr[mid]>key && arr[mid-1]<=key)return mid;
else if(arr[mid]>key)return binary_search(arr,start,mid-1,key);
else return binary_search(arr,mid+1,end,key);
}
答案 3 :(得分:0)
如果向量A的整数范围不宽,则值得考虑位图。 假设A的所有整数都是正数,并且介于0 ... 1024之间,可以使用以下内容构建位图:
#include <bitset>
// ...
// If fixed size is not an option
// consider vector<bool> or boost::dynamic_bitset
std::bitset<1024> bitmap;
for(auto i : A)
bitmap.set(i);
N次迭代设置位,N / 8用于存储位。使用位图,可以按如下方式匹配元素:
std::vector<int> result;
for(auto i = startA; i < endA; ++i) {
if (bitmap[i]) result.emplace_back(i);
}
因此,匹配的速度取决于范围的大小而不是N.当你有许多有限的范围匹配时,这个解决方案应该很有吸引力。