题目描述

给你一座由 n x n 个街区组成的城市,每个街区都包含一座立方体建筑。给你一个下标从 0 开始的 n x n 整数矩阵 grid ,其中 grid[r][c] 表示坐落于 r 行 c 列的建筑物的 高度 。

城市的 天际线 是从远处观察城市时,所有建筑物形成的外部轮廓。从东、南、西、北四个主要方向观测到的 天际线 可能不同。

我们被允许为 任意数量的建筑物 的高度增加 任意增量(不同建筑物的增量可能不同) 。 高度为 0 的建筑物的高度也可以增加。然而,增加的建筑物高度 不能影响 从任何主要方向观察城市得到的 天际线 。

在 不改变 从任何主要方向观测到的城市 天际线 的前提下,返回建筑物可以增加的 最大高度增量总和 。

EX1.

 

输入: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] ]

EX2.

输入:grid = [[0,0,0],[0,0,0],[0,0,0]]

输出:0

解释:增加任何建筑物的高度都会导致天际线的变化。

提示

n == grid.lengthn == grid[r].length2 <= n <= 500 <= grid[r][c] <= 100

代码实现

C语言

 

int min_function(int x,int y)//定义求解两个给定数中较小值的函数 {     if(x

int maxIncreaseKeepingSkyline(int** grid, int gridSize, int* gridColSize) {     int i;     int j;//定义循环变量     int sum=0;//定义函数返回值:增加的天际线总和     int *grid_r=(int*)malloc(gridSize*sizeof(int));     int *grid_c=(int*)malloc(gridSize*sizeof(int));//动态规划:根据给定参数动态分配内存创建数组(一维)     memset(grid_r,0,sizeof(int)*gridSize);     memset(grid_c,0,sizeof(int)*gridSize);//动态数组的初始化方法:卡了好久...后面再说     for(i=0;igrid_r[i])//若当前值大于行最值,存下来             {                 grid_r[i]=grid[i][j];             }             if(grid[i][j]>grid_c[j])//若当前值大于列最值,存下来             {                 grid_c[j]=grid[i][j];             }         }     }     for(i=0;i

思路

      第一眼看到题目就想到了,要记录下行/列的最值,其实东西看过去是一样的,南北看过去是一样的,所以只需要两个变量就可以了,就是行和列。行列数未知,于是使用动态内存分配,二重循环遍历二维数组这个不用说了。我被卡住的地方主要有两个,第一个是刚开始分配的数组如何初始化?我首先尝试了一下静态数组的方法:

grid_r={0};

grid_c={0};

但貌似编译不通过。后面我查了原因是语法错误,这样应该是在定义的时候赋值的,就是应该用:

int arr[5]={0};

而不是像现在这样,先定义了再赋值。

后面换一个思路,在二重循环中第二轮循环开始时假设最大值为第一个元素:

  for(i=0;igrid_r[i])             {                 grid_r[i]=grid[i][j];             }         }     }

编译可以通过,但是测试样例输出数值不对,这一点我有点疑惑...于是抱着疑惑心理打开了题解...最后看到了大佬的思路:

    memset(grid_r,0,gridSize*sizeof(int));     memset(grid_r,0,gridSize*sizeof(int));

???根本没见过?打开AI,打开百度搜索得到答案:

void *memset(void *s, int ch, size_t n);

函数解释:将s中当前位置后面的n个字节 (typedef unsigned int size_t )用 ch 替换并返回 s 。

memset:作用是在一段内存块中填充某个给定的值,它是对较大的结构体或数组进行清零操作的一种最快方法

原来是这样,这里的用法是将grid_r/grid_c中当前位置后面的gridSize*sizeof(int))个字节用0替换并返回grid_r/grid_c。又学到了新的函数!用于数据结构的初始化,抱着学习的心态我又找到了另一种用于初始化动态数组的方法:

使用循环:

int *arr = NULL; int i, n = 5; arr = (int *)malloc(n * sizeof(int)); for(i = 0; i < n; i++) {     arr[i] = i; }

这个问题就研究到这里。我遇到的第二个卡我的地方是后面的计算增加值,还是几个思路:

第一个:用一个新的数组记录增加后的二维数组,然后再遍历两个数组,对应值相减,我认为可行(我没敲)。

第二个:也就是我现在的思路,就是计算每个位置可增加的数,不做记录,最后相加返回(成功实现)。

这个地方主要是思路问题,但其实方法很多,不算难点,难点还是前面的。

总结

      写到这...已经是晚上10:01了,我是8:10开始写的,中间玩了近40分钟手机吧...还是被自己的不自律笑到了,原本说只花30分钟结束战斗然后写物理的,现在看来破灭了...还有就是八点之前一直在宿舍刷推特...真的服了自己的。

       归根到底还是不能自律,有的时候还是要靠外界刺激,他律更适合我。主要今天也纠结了好久要不要买平板...最近一直在物色,感觉精力全花在这个上面了...最晚还是明天就做出决定吧,我觉得不能再浪费我的精力了...今天的收获不少,希望能坚持下去吧。我的梦想很大,只是希望不要做语言上的巨人,行动上的矮子。

文章来源

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。