LeetCode 807. 保持城市天际线
题目描述



题意分析
网格中的每个数表示一栋楼的高度,可以给任意楼增加高度,但不能降低。要求从东、南、西、北四个方向看到的城市天际线保持原样,求所有楼能增加的高度总和的最大值。
沿一行看过去,轮廓高度只由这一行的最高楼决定;反方向看同一行也是相同的最高值,列方向同理。因此四个视角归结为保持每一行、每一列原本的最大高度。返回增加量,不是改造后的楼高总和。
解法:行列最大值
核心思路
[!blue]
先保存原网格每行的最高值
rowMax[i]和每列的最高值colMax[j]。位置(i, j)的新高度不能超过本行最大值,否则会抬高行轮廓;也不能超过本列最大值,否则会抬高列轮廓。因此它的独立上界是min(rowMax[i], colMax[j])。原高度本来就不超过这两个最大值,所以该上界不会低于原楼高,只需增加、不必降低。将当前楼直接升到上界,就是在不突破任何一侧约束时,这一格能取得的最大增量。
所有格子同时升到各自上界也合法。每个新高度都不超过对应行最大值,因此行的最高值不会增加;原本达到行最大值的那栋楼不被降低,所以最高值也不会减少。列方向完全相同,因此整座城市仍保留原来的两组轮廓。
每个格子的理论上界能够同时实现,不存在一栋升高后必须让另一栋少升的冲突。因此把各格的上界减去原高度再相加,就达到了全局最大增加量,无需逐次模拟建筑变化。
解题步骤
- 遍历网格,完整统计每一行和每一列的原始最大高度。
- 再次遍历每个位置,取行、列最大值的较小者作为该楼新高度上界。
- 将上界减去当前高度所得增量累加到答案。
- 返回总增量,原网格无需实际修改。
代码实现
class Solution {
public int maxIncreaseKeepingSkyline(int[][] grid) {
int m = grid.length;
int n = grid[0].length;
int[] rowMax = new int[m];
int[] colMax = new int[n];
for (int i = 0; i < m; 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 answer = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
// 两项上界同时满足,累加的是新高度减原高度
answer += Math.min(rowMax[i], colMax[j]) - grid[i][j];
}
}
return answer;
}
}
func maxIncreaseKeepingSkyline(grid [][]int) int {
m := len(grid)
n := len(grid[0])
rowMax := make([]int, m)
colMax := make([]int, n)
for i := 0; i < m; i++ {
for j := 0; j < n; j++ {
if grid[i][j] > rowMax[i] {
rowMax[i] = grid[i][j]
}
if grid[i][j] > colMax[j] {
colMax[j] = grid[i][j]
}
}
}
answer := 0
for i := 0; i < m; i++ {
for j := 0; j < n; j++ {
limit := rowMax[i]
if colMax[j] < limit {
limit = colMax[j]
}
// 两项上界同时满足,累加的是新高度减原高度
answer += limit - grid[i][j]
}
}
return answer
}
复杂度分析
- 时间复杂度:$O(mn)$,对
m行、n列网格执行两次扫描;题目中的方形网格是其中的特殊情况。- 空间复杂度:$O(m + n)$,分别保存行最大值和列最大值。
关键点总结
[!green]
- 四向天际线只要求保持两组行列最大值。
- 同时受到两个上界限制,单格最高只能取其中较小者。
- 原最高楼不下降、新楼不超界,保证所有位置一起升高仍保持轮廓。
- 求和对象是新旧高度之差,直接计算即可,不必更新输入。
易错点总结
[!yellow]
- 使用行列最大值中的较大者,会突破较低那一侧的轮廓。
- 只约束某一行或某一列,不能同时保证两个方向的天际线。
- 最大值尚未统计完就计算增量,会使用不完整的约束,低估可增加高度。
- 直接累加上界而不减原高度,会返回最终总高度而不是增加量。
相似题目
| 题目 | 难度 | 关联与区别 |
|---|---|---|
| 42. 接雨水 | 困难 | 同样由两侧限制取较小上界,本题上界来自当前行和列最大值,原题来自左右最高边界。 |
| 883. 三维形体投影面积 | 简单 | 同样按行列最大高度概括天际信息,原题累计投影面积,本题在保持这些最大值不变时增加格子高度。 |
转载与许可
许可
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!