
本文详解如何在不依赖 Math 类方法的前提下,通过坐标逻辑准确计算两个轴对齐矩形的并集面积,涵盖重叠判断、交集面积推导及完整可运行代码。
本文详解如何在不依赖 `math` 类方法的前提下,通过坐标逻辑准确计算两个轴对齐矩形的并集面积,涵盖重叠判断、交集面积推导及完整可运行代码。
在二维平面中,给定两个以左上角为基准、宽高非负的轴对齐矩形(即边平行于坐标轴),其并集面积 = 矩形 R1 面积 + 矩形 R2 面积 − 二者交集面积。关键在于鲁棒地计算交集区域的宽度与高度——若无重叠,则交集宽/高为 0,从而交集面积为 0。
核心思路:分离坐标轴计算重叠
由于矩形边与坐标轴平行,x 轴与 y 轴方向的重叠可独立判断:
- x 方向重叠宽度 = max(0, min(R1.right, R2.right) − max(R1.left, R2.left))
- y 方向重叠高度 = max(0, min(R1.bottom, R2.bottom) − max(R1.top, R2.top))
其中:
- R1 左边界 = x1,右边界 = x1 + w1
- R1 上边界 = y1,下边界 = y1 + h1(注意:Java 坐标系中 y 向下增长,但本题约定“top-left”为起点,因此高度向下延伸,该定义与标准图形学一致)
- 同理得 R2 的四条边界。
该公式本质是求两区间 [a1, a2] 与 [b1, b2] 的交集长度:max(0, min(a2, b2) − max(a1, b1))。它天然覆盖所有相对位置关系(完全分离、包含、部分重叠),且无需多层 if-else 判断,简洁、高效、不易出错。
立即学习“Java免费学习笔记(深入)”;
修正后的 Java 实现
import java.util.Scanner;
public class UnionRectangleCalculator {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("- What is the area of the union of two rectangles R1 and R2, where top left corner of R1 is (X1,Y1) and its size is (W1,H1), and top left corner of R2 is (X2,Y2) and its size is (W2,H2)?\n");
System.out.print("Please enter X1, Y1, W1, H1, X2, Y2, W2, H2: ");
int x1 = sc.nextInt();
int y1 = sc.nextInt();
int w1 = sc.nextInt();
int h1 = sc.nextInt();
int x2 = sc.nextInt();
int y2 = sc.nextInt();
int w2 = sc.nextInt();
int h2 = sc.nextInt();
int unionArea = calculateUnionArea(x1, y1, w1, h1, x2, y2, w2, h2);
int area1 = w1 * h1;
int area2 = w2 * h2;
int intersectionArea = area1 + area2 - unionArea;
System.out.println("Result: Intersection area is " + intersectionArea + " thus the total area of the union is " + unionArea + ".");
sc.close();
}
/**
* 计算两个矩形的并集面积(不使用 Math.max/min)
* @return 并集面积
*/
public static int calculateUnionArea(int x1, int y1, int w1, int h1,
int x2, int y2, int w2, int h2) {
// 计算 R1 和 R2 的左右边界、上下边界
int r1Left = x1, r1Right = x1 + w1;
int r1Top = y1, r1Bottom = y1 + h1;
int r2Left = x2, r2Right = x2 + w2;
int r2Top = y2, r2Bottom = y2 + h2;
// 手动实现 max(0, min(rights) - max(lefts))
int overlapX = 0;
int rightMin = (r1Right < r2Right) ? r1Right : r2Right;
int leftMax = (r1Left > r2Left) ? r1Left : r2Left;
if (rightMin > leftMax) {
overlapX = rightMin - leftMax;
}
int overlapY = 0;
int bottomMin = (r1Bottom < r2Bottom) ? r1Bottom : r2Bottom;
int topMax = (r1Top > r2Top) ? r1Top : r2Top;
if (bottomMin > topMax) {
overlapY = bottomMin - topMax;
}
int intersectionArea = overlapX * overlapY;
return w1 * h1 + w2 * h2 - intersectionArea;
}
}关键注意事项
- ✅ 边界处理正确性:使用 min(rights) − max(lefts) 能自然处理“无重叠”情形(结果 ≤ 0 时交集为 0),避免原始代码中因逻辑分支遗漏导致的 OverlapX 或 OverlapY 未初始化为 0 的 bug(如原代码未覆盖 x1 == x2 或完全分离情况)。
- ❌ 原始代码主要缺陷:
- OverlapX/OverlapY 在无重叠时未默认置 0,导致后续 OverlapX * OverlapY 使用了随机初值(Java 中局部变量无默认值,此代码实际无法编译;若为类成员则默认为 0,但逻辑仍不健壮);
- overLapArea = Area - w1 * x2; 是明显笔误,与交集无关;
- 多重嵌套 if 判断易出错,可读性与可维护性差。
- ⚠️ 输入约束:本实现假设 w1, h1, w2, h2 ≥ 0。若需支持负尺寸,应先归一化为非负宽高(取绝对值)并重新计算顶点坐标。
- ? 坐标系说明:题目明确采用“top-left + width/height”定义,y 轴向下为正,因此 y1 + h1 是矩形底边,该设定与算法完全兼容。
运行验证
输入 0 0 5 10 0 0 10 5:
- R1:(0,0) → (5,10),面积 = 50
- R2:(0,0) → (10,5),面积 = 50
- 重叠区域:x∈[0,5], y∈[0,5] → 宽=5,高=5 → 交集面积 = 25
- 并集面积 = 50 + 50 − 25 = 75 ✓
该方案逻辑清晰、无外部依赖、边界安全,是解决此类几何计算问题的标准实践。










