题目描述6043:
给你一个二维整数数组 rectangles ,其中 rectangles[i] = [li, hi] 表示第 i 个矩形长为 li 高为 hi 。给你一个二维整数数组 points ,其中 points[j] = [xj, yj] 是坐标为 (xj, yj) 的一个点。
第 i 个矩形的 左下角 在 (0, 0) 处,右上角 在 (li, hi) 。
请你返回一个整数数组 count ,长度为 points.length,其中 count[j]是 包含 第 j 个点的矩形数目。
如果 0 <= xj <= li 且 0 <= yj <= hi ,那么我们说第 i 个矩形包含第 j 个点。如果一个点刚好在矩形的 边上 ,这个点也被视为被矩形包含。
示例1:
输入:rectangles = [[1,2],[2,3],[2,5]], points = [[2,1],[1,4]]
输出:[2,1]
解释:
第一个矩形不包含任何点。
第二个矩形只包含一个点 (2, 1) 。
第三个矩形包含点 (2, 1) 和 (1, 4) 。
包含点 (2, 1) 的矩形数目为 2 。
包含点 (1, 4) 的矩形数目为 1 。
所以,我们返回 [2, 1] 。
示例2:
输入:rectangles = [[1,1],[2,2],[3,3]], points = [[1,3],[1,1]]
输出:[1,3]
解释:
第一个矩形只包含点 (1, 1) 。
第二个矩形只包含点 (1, 1) 。
第三个矩形包含点 (1, 3) 和 (1, 1) 。
包含点 (1, 3) 的矩形数目为 1 。
包含点 (1, 1) 的矩形数目为 3 。
所以,我们返回 [1, 3] 。
思路:
本题如果暴力求解的话会超出时间限制,所以提出了使用有序list:Sortedlist和树状数组的方式。
from typing import List
from sortedcontainers import SortedList
class Solution:
def countRectangles(self, rectangles: List[List[int]], points: List[List[int]]) -> List[int]:
rectangles.sort(reverse=True) # 按照横、纵坐标倒序排列
points = [(x, y, i) for i, (x, y) in enumerate(points)]
points.sort(reverse=True) # points 也是倒序排列的这样可以减少比较的时间
n = len(rectangles)
res = [0] * len(points)
j = 0 # 指向rectangles
sl = SortedList() # 有序数组:存储rec_y: rectangles[1]
for x, y, i in points:
# 【固定x,二分搜索y】
# 每次循环的时候,不需要对j进行重新赋值,因为points和rec都是降序排列完毕的
print("当前的i, j:", i, j)
while j < n and x <= rectangles[j][0]: # rec_x >= point_x的矩形,其rec_y入列
sl.add(rectangles[j][1]) # 有序数组sl中加入新元素rec_y
j += 1
print(sl)
print("含义:",sl.bisect_left(y))
res[i] = len(sl) - sl.bisect_left(y) # 每次只需要考虑y满足的有几个即可
# sl.bisect_left(y):表示当前有序数组sl中纵坐标 rec_y 比 point_y 小的矩形数目
# 这个函数是一个二分查找的形式,也可以减少时间复杂度
return res
from typing import List
# 树状数组就是求区间和的一种方式
# 本题的思想就是在固定x之后,找满足的y的区间范围内[y, max_y]之间的数量
# 这个数量对应的就是一个数组的区间和(可以用区间和的差值得到)
# 树状数组的一个较大的应用就是前缀和
# 这种利用树状数组求前缀和的方式,在原数组发生改变的时候,求前缀和的时间复杂度会减少,因为是分区间进行求解的
class Solution:
def countRectangles(self, rectangles: List[List[int]], points: List[List[int]]) -> List[int]:
'''树状数组模板''' # 这里需要背下来
def lowbit(x): # lowbit函数
return x & (-x)
def add(i, delta): # 坐标i处依次添加delta
while i < len(tree):
tree[i] += delta
i += lowbit(i)
def query(i): # presum函数
presum = 0
while i > 0:
presum += tree[i]
i -= lowbit(i)
return presum
'''主程序'''
rectangles.sort(reverse=True) # 按照横、纵坐标倒序排列
points = [(x, y, i) for i, (x, y) in enumerate(points)]
points.sort(reverse=True)
# 【固定x,检索y】
max_recy = 0 # 树状数组中元素的最大值
for rec in rectangles:
max_recy = max(max_recy, rec[1]) # 求y的最大值
print(max_recy)
tree = [0] * (max_recy + 1) # 树状数组的大小,这里需要注意加一,因为树状数组是从1开始的
print(tree)
res = [0] * len(points)
j = 0
for (x, y, i) in points:
if y > max_recy: # point_y > rec_y的最大值,没有矩形能够包含
continue
# rec_x >= point_x的矩形,其rec_y放入树状数组中
while j < len(rectangles) and x <= rectangles[j][0]:
add(rectangles[j][1], 1) # 更新树状数组 注意这里树状数组的含义:“+1”部分,思想比较巧妙
j += 1
print("当前i下,树状数组为:", i, tree)
res[i] = query(max_recy) - query(y - 1) # 区间和
return res
2251和本题是完全类似的,只是从二维变成了一维
问题链接
# 相当于和6043相同的,只不过是把比较的数组变成了一维的
# 相当于横坐坐标都是相同的值
# 用排序和树状数组都可以解
from sortedcontainers import SortedList
class Solution(object):
def fullBloomFlowers(self, flowers, persons):
"""
:type flowers: List[List[int]]
:type persons: List[int]
:rtype: List[int]
"""
flowers.sort() # 倒序排列
persons = [(x, i) for i, x in enumerate(persons)]
persons.sort()
n = len(flowers)
j = 0
res = [0] * len(persons)
sl = SortedList()
for x, i in persons:
while j < n and x >= flowers[j][0]:
sl.add(flowers[j][1])
j += 1
res[i] = len(sl) - sl.bisect_left(x)
return res
# 利用树状数组进行求解
class Solution(object):
def fullBloomFlowers(self, flowers, persons):
"""
:type flowers: List[List[int]]
:type persons: List[int]
:rtype: List[int]
"""
flowers.sort()
persons = [(x,i) for i,x in enumerate(persons)]
persons.sort()
# 树状数组模板
def lowbit(x):
return x & (-x)
def add(i, delta): # 在i处加delta
while i < len(tree):
tree[i] += delta
i += lowbit(i)
def query(i): # 前缀和函数
preum = 0
while i > 0:
# print(i)
preum += tree[i]
i -= lowbit(i)
return preum
n = len(flowers)
j = 0
max_f = 0 # 树状数组中元素的最大值
for rec in flowers:
max_f = max(max_f, rec[1]) # 求y的最大值
# print("最大值:", max_f)
tree = [0] * (max_f+1) # !!!这种方式维护一个tree使用的内存太多了
res = [0] * len(persons)
for x, i in persons:
if x > max_f:
continue
while j < n and x >= flowers[j][0]:
add(flowers[j][1], 1)
j += 1
res[i] = query(max_f) - query(x-1)
return res