插: 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。
坚持不懈,越努力越幸运,大家一起学习鸭~~~
题目:
小扣在探索丛林的过程中,无意间发现了传说中“落寞的黄金之都”。而在这片建筑废墟的地带中,小扣使用探测仪监测到了存在某种带有「祝福」效果的力场。 经过不断的勘测记录,小扣将所有力场的分布都记录了下来。forceField[i] = [x,y,side] 表示第 i 片力场将覆盖以坐标 (x,y) 为中心,边长为 side 的正方形区域。
若任意一点的 力场强度 等于覆盖该点的力场数量,请求出在这片地带中 力场强度 最强处的 力场强度。
注意:
力场范围的边缘同样被力场覆盖。
示例 1:
输入: forceField = [[0,0,1],[1,0,1]]
输出:2
解释:如图所示,(0.5, 0) 处力场强度最强为 2, (0.5,-0.5)处力场强度同样是 2。
示例 2:
输入: forceField = [[4,4,6],[7,5,3],[1,6,2],[5,6,3]]
输出:3
解释:如下图所示, forceField[0]、forceField[1]、forceField[3] 重叠的区域力场强度最大,返回 3
提示:
1 <= forceField.length <= 100
forceField[i].length == 3
0 <= forceField[i][0], forceField[i][1] <= 10^9
1 <= forceField[i][2] <= 10^9
java代码:
class Solution {
public int fieldOfGreatestBlessing(int[][] forceField) {
// 1. 统计所有左下和右上坐标
int nf = forceField.length, k = 0;
long[] xs = new long[nf * 2], ys = new long[nf * 2];
for (var f : forceField) {
long i = f[0], j = f[1], side = f[2];
xs[k] = 2 * i - side;
xs[k + 1] = 2 * i + side;
ys[k++] = 2 * j - side;
ys[k++] = 2 * j + side;
}
// 2. 排序去重
xs = unique(xs);
ys = unique(ys);
// 3. 二维差分
int n = xs.length, m = ys.length;
var diff = new int[n + 2][m + 2];
for (var f : forceField) {
long i = f[0], j = f[1], side = f[2];
int r1 = Arrays.binarySearch(xs, 2 * i - side);
int r2 = Arrays.binarySearch(xs, 2 * i + side);
int c1 = Arrays.binarySearch(ys, 2 * j - side);
int c2 = Arrays.binarySearch(ys, 2 * j + side);
// 将区域 r1<=r<=r2 && c1<=c<=c2 上的数都加上 x
// 多 +1 是为了方便求后面复原
++diff[r1 + 1][c1 + 1];
--diff[r1 + 1][c2 + 2];
--diff[r2 + 2][c1 + 1];
++diff[r2 + 2][c2 + 2];
}
// 4. 直接在 diff 上复原,计算最大值
int ans = 0;
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
diff[i][j] += diff[i - 1][j] + diff[i][j - 1] - diff[i - 1][j - 1];
ans = Math.max(ans, diff[i][j]);
}
}
return ans;
}
private long[] unique(long[] a) {
Arrays.sort(a);
int k = 0;
for (int i = 1; i < a.length; i++)
if (a[k] != a[i])
a[++k] = a[i];
return Arrays.copyOf(a, k + 1);
}
}