我想确定每个给定间隔(很多)中有多少个输入数组(最多50000个)。
目前,我尝试使用此算法,但速度太慢了:
示例 - 数组:{ - 3,10,5,4,-999999,999999,6000}
示例间隔:[0,11](含)
O(n * log(n))
。 (-999999,-3,4,5,10,6000,999999)array[min_index] >= 0
- O(n)
。 (对于我的例子,min_index == 2)。array[max_index] <= 11
- O(n)
。 (对于我的例子,max_index == 4)。Result == right_index - left_index + 1
(对于我的例子,Result =(4 - 2 + 1)= 3)。答案 0 :(得分:2)
你有好主意,但需要修改。您应该使用binary search在O(lg n)
时间内找到间隔的开始和结束时间。如果n是数组的长度而q是问题数[a, b]
,那么你有O(n + q * n)时间,二进制搜索它是O((n + q) lg n)
(来自排序数组的n lg n
)。
此解决方案的优点是简单,因为C ++具有std::lower_bound和std::upper_bound。你可以使用std::distance。这只是几行代码。
如果q等于n,则此算法具有O(n lg n)
复杂度。有待改善?一点也不。为什么?因为问题相当于排序。众所周知,不可能获得更好的计算复杂度。 (通过比较排序。)
答案 1 :(得分:1)
有一个简单的O(n 输入 * m interval )算法:
为了便于实施,我们使用半开间隔。根据需要转换你的。
要获得轻微的性能提升,请在步骤2中对limits-array进行排序。
答案 2 :(得分:1)
将数字的std :: map创建为已排序数组中的索引。
从示例地图[-999999] = 0,地图[-3] = 1,...地图[999999] = 7。
要查找间隔,请找到高于或等于min的最小数字(使用map.lower_bound()),并找到高于最大值的第一个数字(使用map.upper_bound())。
您现在可以从上部索引中减去较低的索引,以在O(log n)中查找该范围内的元素数。
答案 3 :(得分:1)
typedef std::pair<int,int> interval;
typedef std::map<interval,size_t> answers;
typedef std::vector<interval> questions;
// O((m+n)lg m)
answers solve( std::vector<int>& data, questions const& qs ){
// m = qs.size()
// n = data.size()
answers retval;
std::vector<std::pair<int, size_t>> edges;
edges.reserve( q.size()+1 );
// O(m) -- all start and ends of intervals is in edges
for ( auto q:qs ) {
edges.emplace_back( q.first, 0 );
edges.emplace_back( q.second, 0 );
}
// O(mlgm) -- sort
std::sort(begin(edges),end(edges));
edges.emplace_back( std::numeric_limits<int>::max(), 0 );
// O(m) -- remove duplicates
edges.erase(std::unique(begin(edges),end(edges)),end(edges));
// O(n lg m) -- count the number of elements < a given edge:
for(int x:data ){
auto it = std::lower_bound( begin(edges), end(edges), std::make_pair(x,0) );
it->second++;
}
// O(m)
size_t accum = 0;
for(auto& e:edges) {
accum += edges.second;
edges.second = accum;
}
// now edge (x,y) states that there are y elements < x.
// O(n lg m) -- find the edge corresponding
for(auto q:questions){
auto low = std::lower_bound(begin(edges), end(edges),
std::make_pair(q.first, size_t(0))
);
auto high = std::upper_bound(begin(edges), end(edges),
std::make_pair(q.second, size_t(0))
}
size_t total = high->second - low->second;
answers.emplace(q,total);
}
return answers;
}
O((n+m)lg m)
,其中n是整数计数,m是区间数,x是每个区间重叠的平均区间数。