【力扣时间】【807】【中等】保持城市天际线

城市天际线?

在这里插入图片描述

1、先看题

点我看题

题目的表述并不清楚,而且已经开始铺陷阱了。所要求的四个方向,实际上两个足矣。
由于是看平面,从前看与从后看,从左看与从右看是完全一样的。

2、审题

善加使用手头的工具。对于二维的题,稍微画画图就能明确出思路。
本人是结合手边的小本本,才得出的思路

题目略有些唬人,不过结合case还是能清楚地分析出其考点。
让我们来康康一些重点:

  1. 何为建筑轮廓?这个其实考验了一点大家的空间逻辑,即为一个角度看时,最高的一个大楼的高度。
  2. case里给足了提示,我们只需要从竖直和水平两个方向分析“天际线”。
  3. 如何变化建筑的高度,才能保持天际线不变呢?变化后的高度不超过该点所在的边或列上的最高点。
  4. 1 < grid.length = grid[0].length <= 50grid数组是一个正方形,且边长最大为50.

3、思路

或许二维数组和长串不着边际的说明有些唬到打击。但实际上,这题在中等难度里也只能算是最为简单的题。

例子里给足了剧透。我们只用从横向和纵向两个纬度,来记录数组里的最大值即可。
于是我们需要初始化两个数组,数组长度和grid[][]的边长一致(由于题目保证了grid为正方形,故长宽一样)。
其次,遍历这个二维数组,对每一个点,比较并记录其所在的边和列上的最大值。
为保证变化后的天际线不变,每个点(建筑)能够提高到的高度为何呢?即为该点所在的边和列的最大值中,较低的一方。

想到这,答案应该就呼之欲出了。

4、开工!

public int maxIncreaseKeepingSkyline(int[][] grid) {
        int[] x = new int[grid[0].length];
        int[] y = new int[grid.length];

        for (int i = 0; i < y.length; i++) {
            for (int t = 0; t < x.length; t++) {
                //遍历二维数组,计算纵向和横向的最大值
                x[t] = Math.max(x[t], grid[i][t]);
                y[i] = Math.max(y[i], grid[i][t]);
            }
        }

        int inc = 0;
        for (int i = 0; i < y.length; i++) {
            for (int t = 0; t < x.length; t++) {
                //比较该点纵向和横向的最大值,获取其较小的一方
                int min = Math.min(x[t], y[i]);
                //差值即为此点的建筑能够增加的高度
                inc += min - grid[i][t];
            }
        }

        return inc;
    }

测试!提交!一气呵成!
让我不得不感慨今天果然还是一道简单题啊。

5、解读

两个数组,两重遍历。其作用和思路里描述的完全一致,这里也不用过多的解读什么的了。
而且关键语句我也写上了注释。

6、提交

虽然执行耗时仅1ms,但排名却落到了83%。
不知道是在什么地方浪费了些许时间,还是又有黑科技出现。

在这里插入图片描述

7、咀嚼

两遍两重循环,时间复杂度为O(N2)Ngrid的边长。
由于使用了两个数组,长度也分别为N,故空间复杂度为O(N)

如果真如我猜想有黑科技,辣么是仅遍历了一遍?还是说能有时间复杂度为O(logN)的二次遍历?

8、他人的智慧

抱着以上的猜想,我惯例翻了翻题解。
却并没有什么收获。
从官解到比较热门的各种大牛的题解里,都是类似的解法。
暴力贪心,简单明了的思路。并没有看到黑科技。

但还是放出一些大牛的题解,供大家学习

大牛们不仅写了分析,还画了图,更加明了地讲解了题目。
让社畜画图是不可能的,这辈子都不可能的。除非遇上什么文字实在无法表述的题再说吧。但文字都说不清了,我还可以鸽啊

9、总结

今天的中等题完全没有中等题的面子。能够收获的大概就只有巩固基础了。
总之今天好歹是周一,各位社畜们想必都有自己的砖要搬,辣么就不多写些什么,各位共勉吧。

弔!我唔想返工啊!
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值