题目
方法一:哈希 + 二分
由题目提示可知:
1
≤
l
i
≤
1
0
9
1
≤
h
i
≤
100
1 \le l_i \le 10^9 \\ 1 \le h_i \le 100
1≤li≤1091≤hi≤100
即矩形的高度范围远远小于矩形宽度。因此考虑对宽度进行二分。
算法流程:
- 创建一个哈希表
map
,key
为矩形的高度,value
为具有相同高度的矩形的宽度,遍历rectangles
,填充该map
,随后,遍历map
,对value
中的矩形宽度集合进行排序,便于后续使用二分查找 - 遍历
points
,对于每个坐标 ( x i , y i ) (x_i,y_i) (xi,yi),遍历[1,100]
范围内的所有高度,在每个大于 y i y_i yi的高度所对应的宽度列表中,进行二分搜索,找到包含点 ( x i , y i ) (x_i,y_i) (xi,yi)的矩形数目
class Solution {
public int[] countRectangles(int[][] rectangles, int[][] points) {
int n = rectangles.length;
// key 高度 value 宽度集合
Map<Integer, List<Integer>> map = new HashMap<>();
for (int i = 0; i < n; i++) {
int l = rectangles[i][0], h = rectangles[i][1];
List<Integer> list = map.getOrDefault(h, new ArrayList<>());
list.add(l);
map.put(h, list);
}
// 对宽度集合进行排序,便于使用二分
for (int key : map.keySet()) {
Collections.sort(map.get(key));
}
int[] count = new int[points.length];
for (int i = 0; i < points.length; i++) {
int x = points[i][0], y = points[i][1];
int cnt = 0;
// 枚举高度
for (int h = 100; h >= 1; h--) {
// 枚举的矩形高小于当前点的高
if (h < y) {
break;
}
// 不存在以当前 h 为高度的矩形,跳过
if (!map.containsKey(h)) {
continue;
}
// 二分搜索
cnt += binarySearchX(map.get(h), x);
}
count[i] = cnt;
}
return count;
}
private int binarySearchX(List<Integer> list, int target) {
int l = 0, r = list.size();
while (l < r) {
int mid = l + (r - l) / 2;
if (list.get(mid) < target) {
l = mid + 1;
} else {
r = mid;
}
}
return list.size() - l;
}
}