问题是: 您将获得一个大小 N 的数组。同时给出 q =查询数量;在查询中,您将获得 l =较低范围, u =较高范围和 num =您需要计算频率的数量升〜U
我用C ++实现了我的代码,如下所示:
#include <iostream>
#include <map>
using namespace std;
map<int,int>m;
void mapnumbers(int arr[], int l, int u)
{
for(int i=l; i<u; i++)
{
int num=arr[i];
m[num]++;
}
}
int main()
{
int n; //Size of array
cin>>n;
int arr[n];
for(int i=0; i<n; i++)
cin>>arr[i];
int q; //Number of queries
cin>>q;
while(q--)
{
int l,u,num; //l=lower range, u=upper range, num=the number of which we will count frequency
cin>>l>>u>>num;
mapnumbers(arr,l,u);
cout<<m[num]<<endl;
}
return 0;
}
但是我的代码有问题,在每个查询中它都没有使地图 m 为空。这就是为什么如果我查询相同的数字两次/三次,它会将频率计数与先前存储的频率相加。
我该如何解决这个问题? 对于大范围的查询,它是一个糟糕的程序,因为10 ^ 5? 什么是这个问题的有效解决方案?
答案 0 :(得分:2)
您可以使用SQRT分解查询来解决任务。复杂性将是 O(M * SQRT(N))。首先,根据以下条件对所有查询进行排序:L / sqrt(N)应该增加,其中L是查询的左边界。对于相等的L / sqrt(N),R(右边界)也应该增加。 N是查询数。然后执行此操作:计算第一个查询的答案。然后,只需将此查询的边界移动逐个下一个查询的边界。例如,如果排序后的第一个查询是[2,7]而第二个是[1,10],则将左边界限移动到1并降低[2]的频率,增加1的频率。将右边界从7移动到10.增加[8],a [9]和[10]的频率。使用地图增加和减少频率。这是一项非常复杂的技术,但它可以很好地解决您的任务。您可以在此处阅读有关查询的SQRT分解的更多信息:LINK
答案 1 :(得分:0)
要清除地图,您需要致电map::clear()
:
void mapnumbers(int arr[], int l, int u)
{
m.clear()
清除问题的更好方法是使m
成为while (q--)
循环的局部变量,甚至是mapnumbers
函数。
然而,总的来说,为什么你需要地图是很奇怪的。无论如何,你遍历整个阵列,你知道你需要计算的数字,所以为什么不这样做
int mapnumbers(int arr[], int l, int u, int num)
{
int result = 0;
for(int i=l; i<u; i++)
{
if (arr[i] == num);
result ++;
}
return result;
}
这将更快,甚至渐近更快,因为map
操作是O(log N),因此您的原始解决方案针对每个查询运行O(N log N),而此简单迭代针对O(N)运行)。
然而,对于一个非常大的数组和许多查询(我猜问题来自一些竞争性的编程网站,不是吗?),这仍然是不够的。我想应该有一些允许O(log N)查询的数据结构和算法,虽然我现在也想不到。
UPD:我刚刚意识到数组不会改变您的问题。这使得它更加简单,允许每个查询解决方案使用简单的O(log N)。您只需要对输入数组中的所有数字进行排序,同时记住它们的原始位置(并确保排序稳定,以便原始位置按递增顺序排列);你只能这样做一次。在此之后,只需两次二进制搜索即可解决每个查询。
答案 2 :(得分:0)
许多算法可用于此类问题。这看起来像是一个直接的数据结构问题。您可以使用Segment树,Square Root Decomposition。检查Geeksforgeeks的算法!我告诉你学习算法的原因是,这种问题有如此大的约束,如果你使用你的方法,你的判决将是TLE。所以更好地使用算法。
答案 3 :(得分:0)
这里的许多答案都很复杂。我将告诉你找到范围频率的简便方法。您可以使用二进制搜索技术在每个查询的 O(logn)中获得答案。
为此,使用vector数组来存储数组中存在的所有数字的索引值,然后使用C ++ STL提供的lower_bound和upper_bound。
这是C ++代码:
#define MAX 1000010
std::vector<int> v[MAX];
int main(){
cin>>n;
for (int i = 0; i < n; ++i)
{
cin>>a;
v[a].push_back(i);
}
int low = 0, high = 0;
int q; //Number of queries
cin>>q;
while(q--)
{
int l,u,num; //l=lower range, u=upper range, num=the number of which we will count frequency
cin>>l>>u>>num;
low = lower_bound(v[num].begin(), v[num].end(), l) - v[num].begin();
high = upper_bound(v[num].begin(), v[num].end(), u) - v[num].begin();
cout<<(high - low)<<endl;
}
return 0;
}
总体时间复杂度: O(Q * log n)