文章目录
- ***今日份每日一题:***
- 题目要求:
- 示例如下:
- 示例1
- 示例2
- 解释
- 剖析示例
- 示例1
- 示例2
- 将逻辑思路转换为代码
力扣官网:前往作答!!!!
今日份每日一题:
题目要求:
-
给你一座由 n x n 个街区组成的城市,每个街区都包含一座立方体建筑。给你一个下标从 0 开始的 n x n 整数矩阵 grid,其中 grid[r][c] 表示坐落于 r 行 c 列的建筑物的高度 。
-
城市的 天际线 是从远处观察城市时,所有建筑物形成的外部轮廓。从东、南、西、北四个主要方向观测到的天际线可能不同。
-
我们被允许为任意数量的建筑物 的高度增加 任意增量(不同建筑物的增量可能不同)。高度为 0 的建筑物的高度也可以增加。然而,增加的建筑物高度不能影响从任何主要方向观察城市得到的天际线 。
-
在不改变从任何主要方向观测到的城市 天际线 的前提下,返回建筑物可以增加的最大高度增量总和 。
示例如下:
示例1
输入:grid = [[3,0,8,4],[2,4,5,7],[9,2,6,3],[0,3,1,0]]
输出:35
解释:建筑物的高度如上图中心所示。
用红色绘制从不同方向观看得到的天际线。
在不影响天际线的情况下,增加建筑物的高度:
gridNew =
[ [8, 4, 8, 7],
[7, 4, 7, 7],
[9, 4, 8, 7],
[3, 3, 3, 3] ]
示例2
输入:grid = [[0,0,0],[0,0,0],[0,0,0]]
输出:0
解释:增加任何建筑物的高度都会导致天际线的变化。
解释
剖析示例
示例1
个人觉得第一遍题目看起来还是比较抽象的,那么画个具体的图加深印象:
- 我将从四个方向观察其天际线
从第一个角度(北边)看起: - 天际线就是最高的那栋楼连起来的线
- 所以我们不需要管最高楼前面和后面的楼,也就是对于天际线来说无论后面和前面的楼高度怎么变,只要大于他就不会变
- 对于北边角度来说,我们只要确保(1,2)坐标的9,(2,3)坐标的4,(3,2)坐标的6以及(4,3)坐标的7在它的这一列中保持最大值就可以了
那么我们来看第二个角度(东边往西边看)的天际线: - 我们只要确保(2,1)的3,(3,2)的6,(4,3)的7以及(3,4)的8保持最大值就可以了
那么我们再来看第三个角度(南边往北边看)的天际线: - 我们只要确保(1,2)的9,(2,3)的4,(3,2)的6以及(4,3)的7保持最大值就可以了
我们来看最后一个方向:
- 我们只要确保(3,4)的8,(4,3)的7,(1,2)的9以及(2,1)的3保持最大值就可以了
- 当我把这些要保持的最大值都圈出来后,再来看这张图
- 我们只需要确保当前值小于所在行,所在列的最大值就能保持天际线不变了
- 这就是变换之后的图
- 我们的最高楼层可以到达所在行和所在列中最大值,但是不能超过它
- 比如坐标(1,1),他需要小于等于9,也需要小于等于3,那么我们选择3时,它满足了天际线的情况
- 虽然他遮住了后面原本天际线的3,但是它变成了现在天际线的3,并没有改变天际线。
- 那么最后计算的结果就是92(增加楼层后的楼层总数)-57(原先的楼层总数)= 35
示例2
输入:grid = [[0,0,0],[0,0,0],[0,0,0]]
输出:0
- 这个比较简单,就不画图了
- 它四个方向的天际线都是0,0,0,0
- 那么它无论增加哪一个楼层都会使它的天际线改变,所以相加后都是0
将逻辑思路转换为代码
逻辑思路:
- 我们需要去寻找高度的限制,也就是行和列的最大高度
- 当我们寻找到行和列的最大高度,我们就可以将当前楼层的高度增加
- 至于如何增加楼层不改变天际线,那就是楼层高度小于等于行和列最大高度,这样就不会改变天际线
- 其实也就是增加到行和列最大值的最小值
- 最后再将当前最高楼层高度减去实际楼层高度
- 最后将这些差值累加起来就是能增加的全部楼层高度
代码:
- 一个数组/队列存放行最大值
- 一个数组/队列存放列最大值
- 第一次循环遍历,找出行和列的最大值,对行和列的最大值进行比较并更换
- 第二次循环遍历,计算能增加的楼层(行和列的最大值的最小值减去当前楼层)
至于为什么是分别找到行和列的最大值,两者的最小值就是最高能增加到的高度,这个还是需要理解一下的
第二次循环遍历其实可以分成两个步骤,一个步骤是计算出当前能增加到的最高高度,再一个步骤去计算两者差值。这边合并在一起了。
代码中需要注意的是行和列,行是i还是j,列是i还是j
int maxIncreaseKeepingSkyline(vector<vector<int>>& grid) {
int n = grid.size(); //记录行和列,用于初始化行和列队列
vector<int> rowMax(n);
vector<int> colMax(n);
int ans = 0;
for(int i=0;i<n;i++){ //双重循环遍历整个grid
for(int j = 0;j<n;j++){
rowMax[i] = max(rowMax[i],grid[i][j]); //比较行,行是外层循环,也就是i,那么就比较rowMax[i]和当前值grid[i][j]
colMax[j] = max(colMax[j],grid[i][j]); //比较列,列是内层循环,也就是j,那么就比较colMax[i]和当前值grid[i][j]
}
}
for(int i = 0; i< n;i++){ //再次遍历获取能增加的高度
for(int j = 0;j<n;j++){
ans+= min(rowMax[i],colMax[j]) - grid[i][j];//获取行和列最大值的最小值,减去当前楼层就是能增加的楼层,再将它们累加
}
}
return ans;
}