LeetCode 883: Projection Area of 3D Shapes (Top + Row Max + Col Max)
LeetCode 883ArrayMatrixToday we solve LeetCode 883 - Projection Area of 3D Shapes.
Source: https://leetcode.com/problems/projection-area-of-3d-shapes/
English
Problem Summary
Given an n x n grid where grid[i][j] is the number of cubes stacked on cell (i, j), return the total projection area on the xy, yz, and zx planes.
Key Insight
The answer is the sum of three independent views: top view counts non-zero cells, front view sums row maxima, and side view sums column maxima.
Algorithm
- Traverse each row and column once.
- If grid[r][c] > 0, contribute 1 to top view.
- Track rowMax for row r and colMax for column r.
- Add all row maxima and column maxima to the total.
- Return top + front + side.
Complexity Analysis
Time: O(n^2).
Space: O(1) extra.
Common Pitfalls
- Forgetting top view uses only non-zero cells, not heights.
- Mixing up row maxima and column maxima.
- Double-count concerns: the three views are intentionally additive.
Reference Implementations (Java / Go / C++ / Python / JavaScript)
class Solution {
public int projectionArea(int[][] grid) {
int n = grid.length;
int top = 0, front = 0, side = 0;
for (int r = 0; r < n; r++) {
int rowMax = 0;
int colMax = 0;
for (int c = 0; c < n; c++) {
if (grid[r][c] > 0) top++;
rowMax = Math.max(rowMax, grid[r][c]);
colMax = Math.max(colMax, grid[c][r]);
}
front += rowMax;
side += colMax;
}
return top + front + side;
}
}func projectionArea(grid [][]int) int {
n := len(grid)
top, front, side := 0, 0, 0
for r := 0; r < n; r++ {
rowMax, colMax := 0, 0
for c := 0; c < n; c++ {
if grid[r][c] > 0 {
top++
}
if grid[r][c] > rowMax {
rowMax = grid[r][c]
}
if grid[c][r] > colMax {
colMax = grid[c][r]
}
}
front += rowMax
side += colMax
}
return top + front + side
}class Solution {
public:
int projectionArea(vector<vector<int>>& grid) {
int n = grid.size();
int top = 0, front = 0, side = 0;
for (int r = 0; r < n; ++r) {
int rowMax = 0, colMax = 0;
for (int c = 0; c < n; ++c) {
if (grid[r][c] > 0) ++top;
rowMax = max(rowMax, grid[r][c]);
colMax = max(colMax, grid[c][r]);
}
front += rowMax;
side += colMax;
}
return top + front + side;
}
};class Solution:
def projectionArea(self, grid: List[List[int]]) -> int:
n = len(grid)
top = front = side = 0
for r in range(n):
row_max = col_max = 0
for c in range(n):
if grid[r][c] > 0:
top += 1
row_max = max(row_max, grid[r][c])
col_max = max(col_max, grid[c][r])
front += row_max
side += col_max
return top + front + sidevar projectionArea = function(grid) {
const n = grid.length;
let top = 0, front = 0, side = 0;
for (let r = 0; r < n; r++) {
let rowMax = 0, colMax = 0;
for (let c = 0; c < n; c++) {
if (grid[r][c] > 0) top++;
rowMax = Math.max(rowMax, grid[r][c]);
colMax = Math.max(colMax, grid[c][r]);
}
front += rowMax;
side += colMax;
}
return top + front + side;
};中文
题目概述
给定一个 n x n 网格,grid[i][j] 表示在单元格 (i, j) 叠放的立方体数量。求该 3D 形体在 xy、yz、zx 三个平面的投影面积总和。
核心思路
总面积可以拆成三部分独立计算:俯视图是非零格子数,正视图是每一行最大值之和,侧视图是每一列最大值之和。
算法步骤
- 一次双层遍历同时处理行和列。
- 若 grid[r][c] > 0,俯视图加 1。
- 维护当前行最大值 rowMax 与当前列最大值 colMax。
- 每行结束后累计到正视图与侧视图。
- 返回 top + front + side。
复杂度分析
时间复杂度:O(n^2)。
空间复杂度:O(1) 额外空间。
常见陷阱
- 把俯视图误算成立方体总数,而不是非零格子数。
- 行最大值和列最大值计算方向写反。
- 误以为三种投影会重复计数,实际上题目要求就是三者求和。
多语言参考实现(Java / Go / C++ / Python / JavaScript)
class Solution {
public int projectionArea(int[][] grid) {
int n = grid.length;
int top = 0, front = 0, side = 0;
for (int r = 0; r < n; r++) {
int rowMax = 0;
int colMax = 0;
for (int c = 0; c < n; c++) {
if (grid[r][c] > 0) top++;
rowMax = Math.max(rowMax, grid[r][c]);
colMax = Math.max(colMax, grid[c][r]);
}
front += rowMax;
side += colMax;
}
return top + front + side;
}
}func projectionArea(grid [][]int) int {
n := len(grid)
top, front, side := 0, 0, 0
for r := 0; r < n; r++ {
rowMax, colMax := 0, 0
for c := 0; c < n; c++ {
if grid[r][c] > 0 {
top++
}
if grid[r][c] > rowMax {
rowMax = grid[r][c]
}
if grid[c][r] > colMax {
colMax = grid[c][r]
}
}
front += rowMax
side += colMax
}
return top + front + side
}class Solution {
public:
int projectionArea(vector<vector<int>>& grid) {
int n = grid.size();
int top = 0, front = 0, side = 0;
for (int r = 0; r < n; ++r) {
int rowMax = 0, colMax = 0;
for (int c = 0; c < n; ++c) {
if (grid[r][c] > 0) ++top;
rowMax = max(rowMax, grid[r][c]);
colMax = max(colMax, grid[c][r]);
}
front += rowMax;
side += colMax;
}
return top + front + side;
}
};class Solution:
def projectionArea(self, grid: List[List[int]]) -> int:
n = len(grid)
top = front = side = 0
for r in range(n):
row_max = col_max = 0
for c in range(n):
if grid[r][c] > 0:
top += 1
row_max = max(row_max, grid[r][c])
col_max = max(col_max, grid[c][r])
front += row_max
side += col_max
return top + front + sidevar projectionArea = function(grid) {
const n = grid.length;
let top = 0, front = 0, side = 0;
for (let r = 0; r < n; r++) {
let rowMax = 0, colMax = 0;
for (let c = 0; c < n; c++) {
if (grid[r][c] > 0) top++;
rowMax = Math.max(rowMax, grid[r][c]);
colMax = Math.max(colMax, grid[c][r]);
}
front += rowMax;
side += colMax;
}
return top + front + side;
};
Comments