一道简单的算法题 -立方体堆叠计算面积-容斥原理(js/golang实现)
刷了一下算法题,分别用js和golang实现了一遍,比较简单的容斥问题
题目
在长度为N的正方形网格上, 堆叠立方体,计算堆叠后整个物体的表面积?
用例
//输入
[
[1, 2, 3],
[1, 0, 0],
[1, 0, 1]
]
//输出
解题思路
容斥原理:(引用百度)
在计数时,必须注意没有重复,没有遗漏。为了使重叠部分不被重复计算,人们研究出一种新的计数方法,这种方法的基本思想是:先不考虑重叠的情况,把包含于某内容中的所有对象的数目先计算出来,然后再把计数时重复计算的数目排斥出去,使得计算的结果既无遗漏又无重复,这种计数的方法称为容斥原理。
因为整个物体形成的形状的有很多种可能性,所以直接计算并不方便
这时候我们直接用容斥原理,首先n个立方体纵向堆叠起来的面积是 n * 4 + 2,而整个物体需要减去的面积就是侧边重叠的部分,为嘛不重复计算,每个柱体只计算南面和西面重叠部分,只要和相邻的柱体比较高度,较低的柱体高度 * 2就是重叠面积, 去掉之后就是整个物体的面积
代码实现
javascript
/**
* @param {number[][]} grid
* @return {number}
*/
var surfaceArea = function(grid) {
let area = 0;
const N = grid.length
for(let i = 0;i < N;i++) {
for (let j = 0,l = grid[i].length;j < l;j++) {
let high = grid[i][j]
if(grid[i][j] != 0) {
//柱体面积
area += (high << 2) + 2
//减去南面重叠
area -= grid[i-1]? (grid[i-1][j] ? Math.min(grid[i-1][j], high) << 1 : 0): 0;
//减去西面重叠
area -= grid[i][j-1] ? Math.min(grid[i][j-1], high) * 2 : 0;
}
}
}
return area
};
golang
func surfaceArea(grid [][]int) int {
area := 0;
N := len(grid);
for i := 0;i < N;i++ {
l := len(grid[i])
for j := 0;j < l;j++ {
high := grid[i][j]
if(grid[i][j] != 0) {
area += high << 2 + 2
if i != 0 && grid[i-1][j] != 0 {
area -= int(math.Min(float64(grid[i-1][j]), float64(high))) << 1
}
if j != 0 && grid[i][j-1] != 0 {
area -= int(math.Min(float64(grid[i][j-1]), float64(high))) << 1
}
}
}
}
return area
}
最后令我有点吃惊的是,两个语言写出来的代码基本逻辑都是一样,但是leetcode用例测试出来的运算时间竟然差了十倍,js大概是70-80ms左右, golang在8ms左右。 不同语言运算效率差是真的大。。。