力扣每日一题:807. 保持城市天际线

力扣官网:前往作答!!!!

今日份每日一题:

题目要求:

  • 给你一座由 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;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

优降宁

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值