Leetcode 850. Rectangular Area II [Difficult]

insert image description here

ps: It was too late yesterday for my colleagues to resign, so I will make up for it today. . .

Topic link and description

https://leetcode.cn/problems/rectangle-area-ii/
We are given a (axis-aligned) two-dimensional rectangle list rectangles. For rectangle[i] = [x1, y1, x2, y2], where (x1, y1) are the coordinates of the lower left corner of rectangle i, (xi1, yi1) are the coordinates of the lower left corner of the rectangle, (xi2, yi2) are the coordinates of the The coordinates of the upper right corner of the rectangle.

Computes the total area covered by all rectangles in the plane. Any area covered by two or more rectangles should only be counted once.

Returns the total area. Since the answer might be too large, return modulo 109 + 7.

Example 1:

Input: rectangles = [[0,0,2,2],[1,0,2,3],[1,0,3,1]]
Output: 6
Explanation: As shown in the figure, three rectangles cover A region with a total area of ​​6.
From (1,1) to (2,2), the green and red rectangles overlap.
From (1,0) to (2,3), all three rectangles overlap.
Example 2:

Input: rectangles = [[0,0,1000000000,1000000000]]
Output: 49
Explanation: The answer is the result of 1018 modulo (109 + 7), which is 49.

hint:

1 <= rectangles.length <= 200
rectangles[i].length = 4
0 <= xi1, yi1, xi2, yi2 <= 109
The total area of ​​the superimposed rectangles will not exceed 2^63 - 1, which means that Use a 64-bit signed integer to store the area result.

Keywords: scan line

Regardless of the coincidence, it is easy to think of dividing the area into 1 equally divided rectangles, find the length of the y-axis, and then add up to get the result

method one:

run screenshot

insert image description here

the code


{
    
    
		// 不考虑重合 很容易想到把区域切分为1等分的矩形,求到y轴长度,然后累加即可得到结果
		// 首先数值需要取模
		long mod = (int) 1e9 + 7;
		// 获得
		List<Integer> xList = new ArrayList<>();
		// 拿到x轴的点集合
		for (int[] info : rectangles) {
    
    
			xList.add(info[0]);
			xList.add(info[2]);
		}
		// 排序
		Collections.sort(xList);
		long ans = 0;
		// 从1开始拿到
		for (int i = 1; i < xList.size(); i++) {
    
    
			int beforeX = xList.get(i - 1), currentX = xList.get(i), len = currentX - beforeX;
			// 因为有重叠,所以可能存在
			if (len == 0) {
    
    
				continue;
			}
			// 然后拿到在这段区域内的 y轴 线段数组
			List<int[]> inYLine = new ArrayList<>();
			for (int[] info : rectangles) {
    
    
				// 如果是包含了当前这段则添加进来
				if (info[0] <= beforeX && currentX <= info[2]) {
    
    
					inYLine.add(new int[]{
    
    info[1], info[3]});
				}
			}
			// 排序,左下角没有重合则先比左下角y,如果重合则比较右上角
			Collections.sort(inYLine, (l1, l2) -> l1[0] != l2[0] ? l1[0] - l2[0] : l1[1] - l2[1]);
			// 加上总面积
			long total = 0, left = -1, right = -1;
			// 循环所有在x轴区域内的y轴线
			for (int[] yRange : inYLine) {
    
    
				// 左小角大于上一个右上角表示没有重叠
				if (yRange[0] > right) {
    
    
					// 记录x段内的总长度为右上角y减去左下角y
					total += right - left;
					// 赋值记录
					left = yRange[0];
					right = yRange[1];
				} else if (yRange[1] > right) {
    
    
					// 如果左下角小于等于上一个右上角 && 右上角大于上一个右上角则不用重复计算
					right = yRange[1];
				}
			}
			// 因为累加是延后一步,所以要再计算一下
			total += right - left;
			// 然后 x 乘 y 得到矩形
			ans += total * len;
			// 取模一下
			ans %= mod;
		}
		return (int) ans;
	}

end

Welcome to communicate in the comment area, check in every day, and rush! ! !

Guess you like

Origin blog.csdn.net/qq_35530042/article/details/126888738