一道簡單的算法題 -立方體堆疊計算面積-容斥原理(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左右。 不同語言運算效率差是真的大。。。