跳转至

883. 三维形体投影面积

题目描述

 n x n 的网格 grid 中,我们放置了一些与 x,y,z 三轴对齐的 1 x 1 x 1 立方体。

每个值 v = grid[i][j] 表示 v 个正方体叠放在单元格 (i, j) 上。

现在,我们查看这些立方体在 xy 、yz 和 zx 平面上的投影

投影 就像影子,将 三维 形体映射到一个 二维 平面上。从顶部、前面和侧面看立方体时,我们会看到“影子”。

返回 所有三个投影的总面积

 

示例 1:

输入:[[1,2],[3,4]]
输出:17
解释:这里有该形体在三个轴对齐平面上的三个投影(“阴影部分”)。

示例 2:

输入:grid = [[2]]
输出:5

示例 3:

输入:[[1,0],[0,2]]
输出:8

 

提示:

  • n == grid.length == grid[i].length
  • 1 <= n <= 50
  • 0 <= grid[i][j] <= 50

解法

方法一:数学

我们可以分别计算三个投影的面积。

  • xy 平面的投影面积:每个非零值都会投影到 xy 平面,所以 xy 的投影面积为非零值的个数。
  • yz 平面的投影面积:每一行的最大值。
  • zx 平面的投影面积:每一列的最大值。

最后将三个面积相加即可。

时间复杂度 $O(n^2)$,其中 $n$ 为网格 grid 的边长。空间复杂度 $O(1)$。

1
2
3
4
5
6
class Solution:
    def projectionArea(self, grid: List[List[int]]) -> int:
        xy = sum(v > 0 for row in grid for v in row)
        yz = sum(max(row) for row in grid)
        zx = sum(max(col) for col in zip(*grid))
        return xy + yz + zx
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
class Solution {
    public int projectionArea(int[][] grid) {
        int xy = 0, yz = 0, zx = 0;
        for (int i = 0, n = grid.length; i < n; ++i) {
            int maxYz = 0;
            int maxZx = 0;
            for (int j = 0; j < n; ++j) {
                if (grid[i][j] > 0) {
                    ++xy;
                }
                maxYz = Math.max(maxYz, grid[i][j]);
                maxZx = Math.max(maxZx, grid[j][i]);
            }
            yz += maxYz;
            zx += maxZx;
        }
        return xy + yz + zx;
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
class Solution {
public:
    int projectionArea(vector<vector<int>>& grid) {
        int xy = 0, yz = 0, zx = 0;
        for (int i = 0, n = grid.size(); i < n; ++i) {
            int maxYz = 0, maxZx = 0;
            for (int j = 0; j < n; ++j) {
                xy += grid[i][j] > 0;
                maxYz = max(maxYz, grid[i][j]);
                maxZx = max(maxZx, grid[j][i]);
            }
            yz += maxYz;
            zx += maxZx;
        }
        return xy + yz + zx;
    }
};
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
func projectionArea(grid [][]int) int {
    xy, yz, zx := 0, 0, 0
    for i, row := range grid {
        maxYz, maxZx := 0, 0
        for j, v := range row {
            if v > 0 {
                xy++
            }
            maxYz = max(maxYz, v)
            maxZx = max(maxZx, grid[j][i])
        }
        yz += maxYz
        zx += maxZx
    }
    return xy + yz + zx
}
1
2
3
4
5
6
7
8
function projectionArea(grid: number[][]): number {
    const xy: number = grid.flat().filter(v => v > 0).length;
    const yz: number = grid.reduce((acc, row) => acc + Math.max(...row), 0);
    const zx: number = grid[0]
        .map((_, i) => Math.max(...grid.map(row => row[i])))
        .reduce((acc, val) => acc + val, 0);
    return xy + yz + zx;
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
impl Solution {
    pub fn projection_area(grid: Vec<Vec<i32>>) -> i32 {
        let xy: i32 = grid
            .iter()
            .map(
                |row|
                    row
                        .iter()
                        .filter(|&&v| v > 0)
                        .count() as i32
            )
            .sum();
        let yz: i32 = grid
            .iter()
            .map(|row| *row.iter().max().unwrap_or(&0))
            .sum();
        let zx: i32 = (0..grid[0].len())
            .map(|i|
                grid
                    .iter()
                    .map(|row| row[i])
                    .max()
                    .unwrap_or(0)
            )
            .sum();
        xy + yz + zx
    }
}

评论