0x01.问题
在
N * N
的网格上,我们放置一些1 * 1 * 1
的立方体。
每个值v = grid[i][j]
表示v
个正方体叠放在对应单元格(i, j)
上。
请你返回最终形体的表面积。
输入示例:[[1,1,1],[1,0,1],[1,1,1]]
输出示例:32
C++函数形式: int surfaceArea(vector<vector<int>>& grid)
0x02.简要分析
初一看,这个问题似乎有点复杂,因为一些正方体重叠起来会产生非常多的重叠空间,我们怎么去去掉这些重复的面积呢,或者,我怎么知道到底有没有重复呢?
我们先来看一个图:
怎么样,是不是发现没有任何思路。
别怕,我们先找一个标志,然后慢慢的去清理去重的思路。
- 第一点,当一个方格上方有
n
个正方体的时候,产生了多大的表面积呢,先不考虑重叠的部分。
很容易发现,当一个格子上有n
个正方体的时候,我们一共产生了两个底面(上底面和下底面),n*4
个侧面,总共就是n*4+2
的面积,这是不考虑重复的情况。
- 第二点,重叠的部分该怎么去掉呢?
首先,我们要清楚,每一个格子上产生的重叠,和哪些格子有关,没错,就是上下左右,四个都有关,而且是在矩阵中,最开始的那部分的左边和上边肯定不要考虑,快要结束的那部分右边和下边不要考虑,我们怎样做到遍历一遍,就能统一一个标准,去掉所有的重复呢?
那就是对每一个格子只考虑左边和上边产生的影响,最开始的不考虑,因为通过遍历,它的右边和下边,最终会成为其它格子的左边和上边,而去重只需要去一次,而且这样最靠近末尾的部分的右边和下边不要考虑,因为没有重叠。
- 第三点,重叠部分面积的计算。
重叠的面积就是两个共同有的,也就是由最矮的那个格子决定的,是最矮格子的两倍,也就是min(v1,v2)*2
。
到这里,我们就只需要一次遍历就可以求出来了。
0x03.解决代码–几何思想
class Solution {
public:
int surfaceArea(vector<vector<int>>& grid) {
int ans=0;
for(int i=0;i<grid.size();i++){
for(int j=0;j<grid.size();j++){
int temp=grid[i][j];
if(temp==0) continue;
ans+=temp*4+2;//一列正方体产生的表面积
ans-=i>0?min(grid[i-1][j],temp)*2:0;//减去左边重叠的面积
ans-=j>0?min(grid[i][j-1],temp)*2:0;//减去上边重叠的面积
}
}
return ans;
}
};
ATFWUS --Writing By 2020–03–25