数组的区间和
输入一个无序的数组nums
,然后可以在O(1)的时间复杂度给出区间ii到jj之间的元素和。
例如:
数组nums
= [1,2,3,4,2,3,1],查询区间下标为1到3之间的元素的和,则返回sum = 2+3+4 = 9
。
如果排序的话,原来的下标之间的相对关系就变了,维护这个相对关系也是十分复杂的,因此排序是不能排序了。
看到O(1)
时间复杂度,想到的应该是类似HashMap子类的数据结构。
数组区间和的问题可以通过记录整个数组元素的前缀和,然后通过两个前缀和相减即可得到区间和。
流程:
- 预处理,
sumMap[i]
表示0到i之间的元素的和; - 计算i到j之间的区间和,利用
sumMap[j] - sumMap[i-1]
即可在O(1)的时间复杂度得到;
public class IntervalSum {
private long[] sumMap = null;
public IntervalSum(int[] num) {
// TODO Auto-generated constructor stub
this.sumMap = new long[num.length];
sumMap[0] = num[0];
for (int i = 1;i < num.length; i++) {
sumMap[i] = num[i] + sumMap[i-1];
}
System.out.println(Arrays.toString(sumMap));
}
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] num = new int[]{1,2,3,4,5,6,7,8,9};
IntervalSum demo = new IntervalSum(num);
System.out.println(demo.querySum(0, 7));
}
public long querySum(int i, int j) {
if (i > j || i < 0 || j >= sumMap.length) return Long.MIN_VALUE;
return sumMap[j] - (i == 0 ? 0 : sumMap[i-1]);
}
}
扩展:
如果某个元素的值被修改,那么sumMap
也相应的需要被修改,但是修改时间复杂度为O(n)
,那么能不能在O(logn)
的时间复杂度达到更新sumMap
的目的呢?答案是:线段树,线段树常常用来解决单点更新,区间查询的问题。
关于线段树的内容,后面继续学习总结。
关于线段树的总结:https://blog.csdn.net/u014532901/article/details/79937786