前缀和

今天我们说一种思想,前缀和思想.
我们就两种前缀和实例来说明.
1.一维前缀和
给定一堆数,找出任意区间的和.
话不多说看代码

public static void fun1() {

		Scanner scan = new Scanner(System.in);

		int count = scan.nextInt();
		int[] sum = new int[count + 1];
		int[] arr = new int[count + 1];
		for (int i = 1; i <= count; i++) {
			int num = scan.nextInt();
			sum[i] = sum[i - 1] + num;  // 前缀和实例
			arr[i] = num;
		}

		System.out.println("请输入区间");
		int start = scan.nextInt();
		int end = scan.nextInt();

		// 获取前缀和
		System.out.println("sum= " + (sum[end] - sum[start - 1]));

	}

sum[i] = sum[i - 1] + num; 这是核心代码
这个相信大家都看的懂
每一项的前面所有元素的和都存储在sum[i] 里面 , 我们如果要得出么个区间的值 可以这样引用
比如 a-b --> sum[b] - sum[a - 1]
2.二维前缀和
问题: 给定一个矩阵,如何得出和最大的子矩阵? 并给出给出子矩阵的开始位置和结束位置

// 二维前缀和
	public static void fun2() {

		Scanner scan = new Scanner(System.in);
		int n = scan.nextInt(); // 矩阵的宽度
		int m = scan.nextInt(); // 矩阵的长度

		int[][] arr = new int[n + 1][m + 1];
		int[][] sum = new int[n + 1][m + 1];

		for (int i = 1; i <= n; i++) {

			for (int j = 1; j <= m; j++) {

				int num = scan.nextInt();
				arr[i][j] = num;
				// 求前缀和
				sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + arr[i][j];
			}
		}

		// 求最大子矩阵 并左顶点坐标 和右顶点坐标

		
		// 保存坐标
		int[] posi = new int[5];

		int max = Integer.MIN_VALUE;
		
		// 下面两层循环表示 枚举所有起点
		for (int i = 1; i <= n; i++) {
			for (int j = 1; j <= m; j++) {
				// 下面两层循环表示 从起点到arr[k][h] 所构成的矩阵  求和
				for (int k = i; k <= n; k++) {
					for (int h = j; h <= m; h++) {
						// 画图可以得出此公式
						int temp = sum[k][h] - sum[i - 1][h] - sum[k][j - 1] + sum[i - 1][j - 1];
						if (temp > max) {
							max = temp;
							posi[1] = i;
							posi[2] = j;
							posi[3] = k;
							posi[4] = h;

						}

					}

				}

			}

		}

		System.out.println("start:(" + posi[1] + "," + posi[2] + ")" + ", end:(" + posi[3] + "," + posi[4] + ")");
		System.out.println("result: " + max);
	}

第一个难点 保存前缀和到二维数组sum[][] 里
看图:
sdacsad
sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + arr[i][j]
这个公式还是比较好理解的
再次回到这个问题,我们要寻找最大字矩阵,我们就需要枚举所有的可能性,没有前缀和之前我们需要六层for循环,有了前缀和之后,只需要四层就行了,
我们枚举每一个点,从每一个点向其他店扩展,就形成了以这个点为起点的所有矩阵,我们比较其大小即可,代码如上,稍微理解下都能想到

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值