我有一个小算法问题。我有一个例如数组。
array[10] = {23,54,10,63,52,36,41,7,20,22};
现在给出一个输入数字,例如189我想知道它应该在哪个插槽中。 例如,此输入应位于数组中的4个索引中,因为
23+54+10+63 = 150 and if we add 52 then sum will be 202 which will cover the range where 189 should lie. so the answer should be 4.
我想找到一个摊销的常数时间算法可能在第一步中我们对数组做了一些预处理,以便我们可以在恒定时间内获得所有下一个查询。
输入数字始终介于1和数组中所有条目的总和之间
感谢
答案 0 :(得分:1)
如果确实需要恒定时间,请创建第二个数组,其大小是包含原始数组索引的最大总和值。所以new_array [189] = 4;
答案 1 :(得分:0)
自然的解决方案是首先使用累积总和构建一个数组。这看起来像
sums[10] = {23,77,87,...}
然后使用二分搜索(例如lower_bound算法)来查找插入位置。那将是O(log(n))
。假设您的插槽数量不变,此解决方案也是时间常数。但我想你希望查找的插槽数量为O(1)
。在这种情况下,您将必须创建一个完整的查找表。由于这些数字的大小相对较小,这是完全可行的:
int lookup[N];
for(i=0,j=0;i<10;i++)
for(k=0;k<sums[i];k++,j++)
lookup[j]=i;
使用此功能,插槽号码只是lookup[number]
。
答案 2 :(得分:0)
我认为你能得到的最好的是使用累积数组并使用二进制搜索以对数时间运行。我不确定是否存在具有恒定时间的解决方案。你确定有吗?
答案 3 :(得分:0)
如果你知道数字总是在1和数组中所有项的总和之间,那么简单的常数时间算法就是建立一个[1..sum]的数组,每个条目包含每个条目的正确插槽数。构建数组,你只需要做一次,是O(N)。然后查找是O(1)。
当然,这假定您有足够的内存用于阵列。
除此之外,我认为你能做的最好的是O(log(N))在总和上使用二元搜索。
答案 4 :(得分:0)
假设
输入数字将始终在1和所有的总和之间 数组中的条目
int total(0), i(0);
for(;total < inputValue; ++i)
{
total += array[i];
}
//your answer is i-1