给定一个数组。我们如何在恒定时间内找到索引间隔(i, j)
中的元素总和。您可以使用额外的空间
例如:
答:3 2 4 7 1 -2 8 0 -4 2 1 5 6 -1
长度= 14
int getsum(int* arr, int i, int j, int len);
// suppose int array "arr" is initialized here
int sum = getsum(arr, 2, 5, 14);
总和应该是恒定时间的10。
答案 0 :(得分:22)
如果您可以花费O(n)时间来“准备”辅助信息,根据这些信息,您可以在O(1)中计算总和,您可以轻松地完成。
准备(O(n)):
aux[0] = 0;
foreach i in (1..LENGTH) {
aux[i] = aux[i-1] + arr[i];
}
查询(O(1)),arr
从1
计算到LENGTH
:
sum(i,j) = aux[j] - aux[i-1];
我认为这是意图,因为,否则,这是不可能的:任何length
计算sum(0,length-1)
你应该扫描整个阵列;这需要线性时间,至少。
答案 1 :(得分:5)
除非您存储信息,否则无法在固定时间内完成。
你必须做一些事情,比如特别修改数组,为每个索引存储数组开头和这个索引之间所有值的总和,然后在范围上使用减法来得到总和的差值。 / p>
但是,您的代码示例中似乎没有任何内容允许这样做。该数组由用户创建(并且可以随时更改),您无法控制它。
任何需要扫描顺序未排序列表中的一组元素的算法都是O(n)。
答案 2 :(得分:2)
以前的答案对于提出的问题绝对没问题。我只是补充一点,如果这个问题有点像:
Find the sum of the interval, if the array gets changed dynamically.
如果数组元素发生了变化,那么我们必须重新计算我们存储在辅助数组中的任何总和,如@ Pavel Shved
方法中所述。
重新计算是O(n)操作,因此我们需要通过使用Segment Tree
将复杂度降低到O(nlogn)。
http://www.geeksforgeeks.org/segment-tree-set-1-sum-of-given-range/
答案 3 :(得分:1)
给出[l,r]
,有三种已知的基于范围的查询算法1.Segment树:总查询时间O(NlogN) 2.Fenwick树:总查询时间O(NlogN) 3.Mo的算法(平方根分解)
前两个算法可以处理给你的列表/数组中的修改。第三种算法或Mo的算法是离线算法,意味着之前需要向您提供所有查询。此算法中不允许对列表/数组进行修改。对于此算法的实现,运行时和进一步阅读,您可以查看此Medium博客。它用代码解释。而且很少有人真正了解这种方法。
答案 4 :(得分:0)
这个问题将解决O(n ^ 2)时间,O(n)空间或O(n)时间,O(n)空间..
现在是这种情况下最佳的最佳解决方案(即O(n)时间,O(n)) 假设给出了一个[] = {1,3,5,2,6,4,9} 如果我们创建一个数组(sum []),其中我们将0索引的和值保存到该特定索引。对于数组a [],sum数组将是sum [] = {1,4,9,11, 17,21,30};像 {1,3 + 1,3 + 1 + 5 ......}这需要O(n)时间和O(n)空间。 当我们给索引然后它直接从sum数组中获取它意味着add(i,j)= sum [j] -sum [i-1];这需要O(1)次和O(1)空格...... 所以,这个程序需要O(n)时间和O(N)空间..
int sum [] = new int [l];
sum[0]=a[0];
System.out.print(cumsum[0]+" ");
for(int i=1;i<l;i++)
{
sum[i]=sum[i-1]+a[i];
System.out.print(sum[i]+" ");
}
?*这给出1,4,9,11,17,21,30并且花费O(n)时间和O(n)空格* /
sum(i,j)= sum [j] -sum [i-1] / 这给出了从i到j的索引之和,取O(1)时间和O(1)空间 /
所以,这个程序需要O(n)时间和O(N)空格.. 强调文本