需求:sum(int[] nums,int l,int r),此方法用来求数组上[l,r]上的和,且调用频繁。如何设计更高效?
解析:肯定不是每次调用sum时,sum都重新将[l,r]上遍历求和。
答案:建立前缀和数组是其中一种有效的解决方法。
前缀和数组本质还是数组,先计算好结果并存储到里面,每次需要结果时,直接从里面拿。
int[] nums = new int[]{1,4,5,6,7,0,-9};
该数组对应的前缀和数组help是:1,5,10,16,23,23,14
help[i]表示nums数组中【0,i】这个区间上元素的累加和
求【3,7】上的和?
help[2] 是0~2
help[7] 是 0~7
所以,help[7] - help[2] 就是去掉重复的部分,就是【3,7】上的和
求【l,r】上的和?
若l !=0,【l,r】上的和 = help[ r] - help[l-1] 。若l==0,直接help拿[r],因为没有help[-1]. (边界条件)
只需要在前缀和数组里拿到两个数后相减即可。
package arrayAndString;
import org.junit.Test;
/**前缀和数组
*/
public class prefixArr {
//将前缀和数组声明为属性
private int[] help;
//生成前缀和数组。构造器
public prefixArr(int[] nums){
int N = nums.length;
help = new int[N];
//help[i]表示nums数组中【0,i】累加和
help[0] = nums[0];
for (int i = 1; i <N ; i++) {
//nums[i]数组里的当前元素
help[i] = help[i-1]+nums[i];
}
}
public int getSum(int L,int R){
return L == 0 ? help[R] : help[R]-help[L-1];
}
}
测试:
public class testPerfixArr {
@Test
public void t(){
int[] nums = new int[]{1,4,5,6,7,0,-9};
prefixArr prefixArr = new prefixArr(nums);
int sum = prefixArr.getSum(0, 0);
System.out.println(sum);
}
}