一道簡單的算法題 -立方體堆疊計算面積-容斥原理(js/golang實現)

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章