44. 开发商购买土地
前缀和
思路
可能的情况有两类,A占前 i 行,B占剩余行;A占前 j 列,B占剩余列。
若直接暴力枚举,第一层 for 循环遍历行(控制行的切分),第二层、第三层 for 循环计算A区域中元素和,时间复杂度O(n^3)。
1、计算每行的和,得到行前缀和数组horizontoal,horizontoal[i]表示第i行元素和,
计算每列的和,得到列前缀和数组vertical,vertical[j]表示第j行元素和。
2、枚举按行切分的情况,计算差值,
枚举按列切分的情况,计算差值。
时间复杂度O(n^2)
import java.util.Scanner;
public class Main {
public static void main (String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int m = scanner.nextInt();
int sum = 0;
int[][] vec = new int[n][m];
// 初始化并计算数组元素和
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
vec[i][j] = scanner.nextInt();
sum += vec[i][j];
}
}
// 行前缀和
int[] horizontoal = new int[n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
horizontoal[i] += vec[i][j];
}
}
// 列前缀和
int[] vertical = new int[m];
for (int j = 0; j < m; j++) {
for (int i = 0; i < n; i++) {
vertical[j] += vec[i][j];
}
}
int res = Integer.MAX_VALUE;
// 水平切分
int horizontoalCut = 0; // 前 i 行元素的和
for (int i = 0; i < n; i++) {
horizontoalCut += horizontoal[i];
res = Math.min(res, Math.abs(horizontoalCut - (sum - horizontoalCut)));
}
// 垂直切分
int verticalCut = 0; // 前 j 列元素的和
for (int j = 0; j < m; j++) {
verticalCut += vertical[j];
res = Math.min(res, Math.abs(verticalCut - (sum - verticalCut)));
}
System.out.println(res);
scanner.close();
}
}
进阶