范围求和
实现需求
给一个数组long arr[] = {3,4,7,1,6,8,1,36,8,9…,n},, 设计一个函数返回 l~r 范围的求和 。 long rangeSum(int l, int r){ … }
方式1:一维数组
定义一个一维数组 sum[0,1…,m,n] ; sum[m]存放数组0 ~ m的和,sum[n]存放数组0~n的和;计算从 m~n 的和:sum[n] - sum[m-1];
static class RangeSum1 {
long[] sum;
public RangeSum1(long[] arr) {
// 初始化一维数组
sum = new long[arr.length];
sum[0] = arr[0];
for (int i = 1; i < arr.length; i++) {
sum[i] = arr[i] + sum[i - 1];
}
}
public long rangeSum(int l, int r) {
return l == 0 ? sum[r] : sum[r] - sum[l - 1];
}
}
方式2:矩阵列表(二维数组)
定义一个二维数组 sum[y] [x]; sum[y] [x]表示从y~x范围的和;比如:计算从 8~100 的和:sum[8] [100];
static class RangeSum2 {
long[][] sum;
public RangeSum2(long[] arr) {
// 初始化矩阵
sum = new long[arr.length][arr.length];
for (int y = 0; y < arr.length; y++) {
sum[y][y] = arr[y];
for (int x = y + 1; x < arr.length; x++) {
sum[y][x] = sum[y][x - 1] + arr[x];
}
}
}
public long rangeSum(int l, int r) {
return sum[l][r];
}
}
测试
public static void main(String[] args) {
long[] arr = {1, 2, 3, 4, 5, 7, 8, 9, 11, 34, 67, 88};
int from = 0, to = 9;
RangeSum1 rangeSum1 = new RangeSum1(arr);
System.out.println(rangeSum1.rangeSum(from, to));
RangeSum2 rangeSum2 = new RangeSum2(arr);
System.out.println(rangeSum2.rangeSum(from, to));
}
输出结果:84 84
优缺点
两种结构都是通过预先存放计算结果,范围计算直接取值,不用每次去计算
一维数组:节省空间,需要做一次减法操作,效率稍慢
矩阵列表:空间利用率为1/2,范围求和直接根据下标返回。效率高