3长度AP的阵列最快的算法计数 [英] fastest algorithm count number of 3 length AP in array
问题描述
我要解决这 codeChef挑战:
I want to solve this CodeChef challenge:
假设我们给出N的数组A(范围100,000)的元素。我们要找出所有对3个这样的元素1 LT的数量=爱,AJ,阿克< = 30,000使得
AJ-艾= AK-AJ和I< J<氏/ code>
换句话说艾,AJ,阿克都在算术级数。例如,对于阵:
Suppose We are given an array A of N(of range 100,000) elements. We are to find the count of all pairs of 3 such elements 1<=Ai,Aj,Ak<=30,000 such that
Aj-Ai = Ak- Aj and i < j < k
In other words Ai,Aj,Ak are in Arithmetic Progression. For instance for Array :
9 4 2 3 6 10 3 3 10
所以AP是:
so The AP are:
{2,6,10},{9,6,3},{9,6,3},{3,3,3},{2,6,10}
因此,所需的答案是5。
So the required answer is 5.
我试过是拿3万评为过去,右长的阵列。最初,右包含每个1-30,000元素的数量。
如果我们在第i个位置经过许多商店数组值的前阵我和右侧存储计计数后,我。我简单地循环为阵列中的所有可能的公差。这里是code:
What I tried is take 30,000 long arrays named past and right. Initially right contains the count of each 1-30,000 element.
If we are at ith position past stores the count of array value before i and right stores the count of array after i. I simply loop for all possible common difference in the array. Here is the code :
right[arr[1]]--;
for(i=2;i<=n-1;i++)
{
past[arr[i-1]]++;
right[arr[i]]--;
k=30000 - arr[i];
if(arr[i] <= 15000)
k=arr[i];
for(d=1;d<=k;d++)
{
ans+= right[arr[i] + d]*past[arr[i]-d] + past[arr[i] + d]*right[arr[i]-d];
}
ans+=past[arr[i]]*right[arr[i]];
}
但是,这让我的时间超出限制。请帮助一个更好的算法。
But this gets me Time Limit Exceeded. Please help with a better algorithm.
推荐答案
您可以大大节省运行时间,如果你犯了一个先传过来的名单,只提取数对,有可能有(差之间的3学期AP是0模2)。而这种对之间再进行迭代。
You can greatly cut execution time if you make a first pass over the list and only extract number pairs that it is possible to have an 3 term AP between (difference is 0 mod 2). And then iterating between such pairs.
伪C ++ - Ÿcode:
Pseudo C++-y code:
// Contains information about each beginning point
struct BeginNode {
int value;
size_t offset;
SortedList<EndNode> ends; //sorted by EndNode.value
};
// Contains information about each class of end point
struct EndNode {
int value;
List<size_t> offsets; // will be sorted without effort due to how we collect offsets
};
struct Result {
size_t begin;
size_t middle;
size_t end;
};
SortedList<BeginNode> nodeList;
foreach (auto i : baseList) {
BeginNode begin;
node.value = i;
node.offset = i's offset; //you'll need to use old school for (i=0;etc;i++) with this
// baseList is the list between begin and end-2 (inclusive)
foreach (auto j : restList) {
// restList is the list between iterator i+2 and end (inclusive)
// we do not need to consider i+1, because not enough space for AP
if ((i-j)%2 == 0) { //if it's possible to have a 3 term AP between these two nodes
size_t listOffset = binarySearch(begin.ends);
if (listOffset is valid) {
begin.ends[listOffset].offsets.push_back(offsets);
} else {
EndNode end;
end.value = j;
end.offsets.push_back(j's offset);
begin.ends.sorted_insert(end);
}
}
}
if (begin has shit in it) {
nodeList.sorted_insert(begin);
}
}
// Collection done, now iterate over collection
List<Result> res;
foreach (auto node : nodeList) {
foreach (auto endNode : node.ends) {
foreach (value : sublist from node.offset until endNode.offsets.last()) {
if (value == average(node.value, endNode.value)) {
// binary_search here to determine how many offsets in "endNode.offsets" "value's offset" is less than.
do this that many times:
res.push_back({node.value, value, endNode.value});
}
}
}
}
return res;
这篇关于3长度AP的阵列最快的算法计数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!