java-求一个数组中(L-R)位置的累加和

求一个数组(L - R)位置的累加和

假设有一个数组arr,下面表格表示当前数组的数据

数组值329587
 数组下标012345

第一种方式:可以生成一个矩阵形式的表(L在下图位置表示纵向位置的坐标,R在下图位置表示横向位置的坐标),这种方式比较浪费空间,但是查询效率会高,因为查L - R 位置的累加和,可以从中直接取出值,不需要再次计算。

数组下标R/数据下标L012345
0

   3

514192734
1X211162431
2XX9142229
3XXX51320
4XXXX815
5XXXXX7

表格中单元格中的值表示数组 L - R 位置上值的累加和,单元格中值为 X 表示无效范围,不会出现 1 - 0,2 - 0,2 - 1,3 - 0,3 - 1, ······ 范围的值;
表格第一行 表示 0 - 0 位置上的累加和为数组arr[0] 值 3, 0 - 1 位置的累计和为5,0 - 2 位置的累计和为14,······ 0 - 5 位置的累计和为34;
第二行 表示 1 - 0 位置 为无效范围,1 - 1 位置的累计和为2,1 - 2 位置的累计和为11,1 - 3 位置的累计和为16,1 - 4 位置的累计和为24,1 - 5 位置的累计和为31;
······

public class RangSum {
	/**
	 * 帮助查询 数组
	 * 保存 0 - 1,0 -2 ,0 - 3 ,······ ,0 - N 位置的 累加和
	 * 1 - 1 ,1 - 2, 1 - 3,······ ,0 - N 位置的 累加和
	 */
	private int[][] rangSum;
    
    /**
    *生成 累加和 矩阵
    */
	public void generateRangSum(int[] arr) {
		int length = arr.length;
		rangSum = new int[length][length];
		for (int i = 0; i < length; i++) {
			for (int j = i; j < length; j++) {
				if(j > i){
					rangSum[i][j] = rangSum[i][j-1] + arr[j];
				}/*else if(i > j){ //因为第二层循环 每次都是从i位置开始,所以不会有 i > j 的情况,所以可以省略当前判断
						rangSum[i][j] = 0;
					}*/else {
					rangSum[i][j] = arr[j];
				}
			}
		}
	}

	/**
	 * 获取L - R 范围的累加和
	 * @param L 开始下标
	 * @param R 结束下标
	 * @return
	 */
	public int getRangSum(int L,int R){
		return rangSum[L][R];
	}
	
	public static void main(String[] args) {
		int[] arr = {3,2,9,5,8,7};
		RangSum rangSum = new RangSum();
		rangSum.generateRangSum(arr);
		System.out.println(rangSum.getRangSum(1,2));
		// 结果 11
	}
}

第二种方式:可以用一个数组H保存0 - 0 位置,0 - 1 位置,0 - 2 位置,······,0 - N 位置的前缀和。这种方式节省空间,但查询效率不如第一种,需要计算一次。

数组下标R/数据H012345
H[]

   3

514192734

假设查询 2 - 4 位置的累加和,(H[4] - H[2-1])只需取出 数组H,4 位置的值27 和 2 - 1 位置的值5,27 - 5,即可得到结果 22。

public class RangSum {
	/**
	 * 帮助查询 数组
	 * 保存 0 - 1,0 -2 ,0 - 3 ,······ ,0 - N 位置的 前缀和
	 */
	private int[] preSum;

	public void generatePreSum(int[] arr){
		preSum = new int[arr.length];
		//0 - 0 位置的结果是是数组arr[0]自己本身,提前可以确定
		preSum[0] = arr[0];
		/**
		 * 0 - 1 位置的前缀和等于 arr[0] + arr[1]
		 * 0 - 2 位置的前缀和等于 arr[0] + arr[1] + arr[2] =  0 - 1 位置的前缀和(perSum[1])  加 arr[2] 
		 * 0 - 3 位置的前缀和等于 arr[0] + arr[1] + arr[2] + arr[3] =  0 - 2 位置的前缀和(perSum[2])  加 arr[3] 
		 * ······
		 */
		for (int i = 1; i < arr.length; i++) {
			preSum[i] = preSum[i-1] + arr[i];
		}
	}

	/**
	 * 获取L - R 范围的累加和
	 * @param L 开始下标
	 * @param R 结束下标
	 * @return
	 */
	public int getRangSum(int L,int R){
		if(L > R){
			return 0;
		}
		return L == 0 ? preSum[R] : preSum[R] - preSum[L - 1];
	}

	public static void main(String[] args) {
		int[] arr = {3,2,9,5,8,7};
		RangSum rangSum = new RangSum();
		rangSum.generatePreSum(arr);
		System.out.println(rangSum.getRangSum(1,2));
		// 结果 11
	}
}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值