文章目录
前言
城市天际线是一道有趣而简单的算法
我们能使用贪心法解决
描述:
给你一座由 n x n 个街区组成的城市,每个街区都包含一座立方体建筑。给你一个下标从 0 开始的 n x n 整数矩阵 grid ,其中 grid[r][c] 表示坐落于 r 行 c 列的建筑物的 高度 。
城市的天际线:
是从远处观察城市时,所有建筑物形成的外部轮廓。
从东、南、西、北四个主要方向观测到的 天际线 可能不同。
我们被允许为 任意数量的建筑物 的高度增加 任意增量(不同建筑物的增量可能不同) 。 高度为 0 的建筑物的高度也可以增加。然而,增加的建筑物高度 不能影响 从任何主要方向观察城市得到的 天际线 。
在 不改变 从任何主要方向观测到的城市 天际线 的前提下,返回建筑物可以增加的 最大高度增量总和 。
一、解题思路
1.当城市的布局如下图时,城市的天际线就如图一、图二所示。
图一:
图二:
2.所以不改变天际线的情况下要考虑:
1)从每行中选出最高的一个
红色所示,就是每行最高
2)从每列中选出最高的一个
黄色所示,就是每列最高
3)选出每行每列最高值中最低的
如:
第一行第一列(1,1):
行最高为8,列最高为9
则选择8作为此块区域(1,1)的最高值
(1,2):
行最高为8,列最高为4
则选择4作为此块区域(1,2)的最高值
…
依次比较
3.最终结果
当前区域内建筑高度与之前的高度相减后求和即可得出结果:
x = (8-3) + (4-0) + (8-8) + (7-4) + (7-2) + (4-4) + (7-5) + (7-7) +(9-9) + (4-2) + (8-6) + (7-3) + (3-0) + (3-3) + (3-1) + (3-0) = 35
二、代码实现
代码如下:
public int maxIncreaseKeepingSkyline(int[][] grid) {
//获取该二维数组的长度
int n = grid.length;
//定义数组储存每行最高的建筑高度
int[] rowMax = new int[n];
//定义数组储存每列最高的建筑高度
int[] colMax = new int[n];
//遍历二维数组,选出行最高与列最高存入对应的数组
for(int i = 0;i < n;i++) {
for(int j = 0;j < n;j++) {
rowMax[i] = Math.max(rowMax[i],grid[i][j]);
colMax[j] = Math.max(colMax[j],grid[i][j]);
}
}
//设置变量存储结果
int ans = 0;
//遍历二维数组,
for(int i = 0;i < n;i++) {
for(int j = 0;j < n;j++) {
//找出每个区域可以达到的最高高度,并与之前的高度相减
//并求和
ans += Math.min(rowMax[i],colMax[j]) - grid[i][j];
}
}
//返回最终结果
return ans;
}
总结
这道算法非常简单,本次代码实现使用的是贪心,在空闲时可以在纸上画一画图,可以活跃思维,非常有趣。