【刷题日记】807. 保持城市天际线

759 阅读4分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第27天,点击查看活动详情

【刷题日记】807. 保持城市天际线

本次刷题日记的第 47 篇,力扣题为:807. 保持城市天际线中等

一、题目描述:

1.png

祝 xdm 节日快乐,在回家的最后一天,咱们还是先把文章记录一波吧,最后 2 天了,肝到底

2.gif

二、这道题考察了什么思想?你的思路是什么?

迅速来瞅瞅这个题给我们说了什么是天际线:

  • 题目给出我们的一个表格,表格上的数字表示这栋建筑的高度,这个表格是一个俯视图,实际上他是一个立体图,我们可以从四个方向看来这个立体图形映射到每隔方向的阴影
  • 那么天际线就是上述每隔方向投射出阴影的最上方的外部轮廓
  • 题目要求我们在不改变天际线的情况下,尽可能多的增加现有建筑的高度

看前面 2 个可能还不知道题目需要我们搞啥,乍一看可能还有点晕,但是看到题目的要求和天际线的明确解释之后,好像有点眉目了

那么这里我们就可以来分析一下了,看上去还是很容易的

我们至少上述的投影,其实是已经被每隔方向上的最高建筑给决定了天际线的,那么我们是不是只要在不超出每个方向最高建筑物的条件下对其余涉及的建筑物增加高度就可以了呢?

有了这个思路之后,其实解题就非常明确了

  • 我们可以记录每一行,和每一列的最大值
  • 遍历一下整个表格,看看当前表格的行上面的最大值,和列上面的最大值,谁小,咱们用较小的一个减去当前格子对应建筑物的高度,那么就是我们需要对当前格子增加的高度了
  • 解释一下,第二点,我们需要考虑到四个方向上的投影,因此我们取的是行列最大值中的较小的一个

有了这个清晰,且明确的思路,接下来就是撸起袖子撸代码了

三、编码

根据上述逻辑和分析,我们就可以翻译成如下代码,这里需要注意好边界,以及需要先明确计算出每一行和每一列的最大值,为之后的计算做好铺垫

编码如下:

func maxIncreaseKeepingSkyline(grid [][]int) (res int) {
    n := len(grid)
    // 定义好每一行和每一列要存储最大值的结构
    colMax := make([]int, n)
    // 计算出每一个行和每一列的最大值
    for i, row := range grid {
        for j, h := range row {
            rowMax[i] = max(rowMax[i], h)
            colMax[j] = max(colMax[j], h)
        }
    }
    // 遍历表格,对于每一个格子,获取他所在行和列的最小值,再减去当前的格子对应的高度,则是当前格子还能增加的高度(在不影响天际线的前提下)
    for i, row := range grid {
        for j, h := range row {
            res += min(rowMax[i], colMax[j]) - h
        }
    }
    return
}

func max(a, b int) int {
    if b > a {
        return b
    }
    return a
}

func min(a, b int) int {
    if a > b {
        return b
    }
    return a
}

按照这样的方式来进行实现的话,咱也比较好理解,仔细再回过头来看看,逻辑也是很清晰的

四、总结:

对于我们这种方式来实现的,时间复杂度是 O(n^2) ,这里比较明确,因为我们直接是遍历了整个表格,表格的宽是 n,高也是 n,因此 遍历完整个表格就是 n^2

那么空间复杂是不是也是 O(n^2) 呢?

并不是,因为们只是开辟了 2 个长度为 n 的数组,时间上我们在空间消耗上是增加 O(n) 级别的空间消耗,因此此处的空间复杂度是 O(n)

原题地址:807. 保持城市天际线

今天就到这里,学习所得,若有偏差,还请斧正

欢迎点赞,关注,收藏

朋友们,你的支持和鼓励,是我坚持分享,提高质量的动力

好了,本次就到这里

技术是开放的,我们的心态,更应是开放的。拥抱变化,向阳而生,努力向前行。

我是小魔童哪吒,欢迎点赞关注收藏,下次见~