一道简单的算法题 -立方体堆叠计算面积-容斥原理(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左右。 不同语言运算效率差是真的大。。。

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