文章目录
223. 矩形面积
给你 二维 平面上两个 由直线构成的 矩形,请你计算并返回两个矩形覆盖的总面积。
每个矩形由其 左下 顶点和 右上 顶点坐标表示:
第一个矩形由其左下顶点 (ax1, ay1) 和右上顶点 (ax2, ay2) 定义。
第二个矩形由其左下顶点 (bx1, by1) 和右上顶点 (bx2, by2) 定义。
输入:ax1 = -3, ay1 = 0, ax2 = 3, ay2 = 4, bx1 = 0, by1 = -1, bx2 = 9, by2 = 2
输出:45
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/rectangle-area
题解
两个矩形面积之和减去覆盖面积
覆盖面积通过覆盖的坐标区间去求
class Solution:
def computeArea(self, ax1: int, ay1: int, ax2: int, ay2: int, bx1: int, by1: int, bx2: int, by2: int) -> int:
s = (ax1-ax2)*(ay1-ay2)+(bx1-bx2)*(by1-by2)
if ax2<=bx1 or ax1>=bx2 or ay1>=by2 or ay2<=by1: return s
xs = [ax1,ax2,bx1,bx2]
ys = [ay1,ay2,by1,by2]
xs.sort()
ys.sort()
return s-((xs[1]-xs[2])*(ys[1]-ys[2]))
850. 矩形面积 II
我们给出了一个(轴对齐的)矩形列表 rectangles 。 对于 rectangle[i] = [x1, y1, x2, y2],其中(x1,y1)是矩形 i 左下角的坐标,(x2,y2)是该矩形右上角的坐标。
找出平面中所有矩形叠加覆盖后的总面积。 由于答案可能太大,请返回它对 10 ^ 9 + 7 取模的结果。
示例 1:
输入:[[0,0,2,2],[1,0,2,3],[1,0,3,1]]
输出:6
解释:如图所示
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/rectangle-area-ii
思路
- 拿到所有的x,去重之后按顺序排列,对应在坐标轴上
- 找到每一个x对应的y轴的有效区间覆盖,如下图调试代码
- 我们将一个矩形的纵坐标 y1,y2 打包成一个列表, 放入 [x1,x2)区间中
- 若 [x1,x2)区间 有x1,x3,x4 这三个坐标,则以这三个坐标为键,存储他们覆盖的y区间
- 则x1:[y1,y2],x3:[y1,y2],x4:[y1,y2]
- 算出所有矩形覆盖的区间
- 将键对应的区间融合起来,求有效区间长度和
三个坐标为键,存储他们覆盖的y区间
题解- 坐标投影 -线段覆盖 - 有效区间计算
class Solution:
def rectangleArea(self, rectangles) -> int:
ans = 0
'''
映射矩形的x坐标到坐标轴
'''
rectangles.sort()
xs=[]
for x1, y1, x2, y2 in rectangles:
xs.append(x1)
xs.append(x2)
xs = list(set(xs))
xs.sort()
'''
找x对应的y区间
'''
cy = {}
for x1, y1, x2, y2 in rectangles:
for i in range(len(xs)-1):
if i not in cy: cy[i] = []
if x1<=xs[i]:
if x2>xs[i]:
cy[i].append([y1,y2])
else:
break
'''
求有效区间长度
'''
def mergeqj(xs):
if len(xs) == 0:return 0
ys = 0
xs.sort()
l,r = xs[0]
for ll,rr in xs[1:]:
if ll > r:
ys+=r-l
l = ll
r = rr
else:
r = max(r,rr)
ys += r-l
return ys
'''
求面积
'''
for i in range(0,len(xs)-1):
y = mergeqj(cy[i])
ans += (xs[i+1]-xs[i])*y
return int(ans%(10**9+7))
pow 指数计算在大范围内失效的问题 - 精度
从测试用例的通过情况来看
from math import pow
int(ans%(pow(10,9)+7)) 与 int(ans%(10**9+7)) 得到了不同的答案,且前者答案是错误的
输出
862275785
预期结果
862275791
在小范围内,用pow没问题
在大范围内,用pow是错的
前面的用例能通过,但是超过某个范围就错误了,原因在于pow函数
从math.pow()库函数的定义来看
对于幂函数pow,是用数值逼近的方法给出的,并不保证严格精确,执行效率也不高,在不同平台精确度可能有一定的差异,所以也就会导致结果不是我们预期想要的
来源:https://blog.csdn.net/wuli_dear_wang/article/details/80373255
”对于幂函数pow,是用数值逼近的方法给出的,并不保证严格精确,执行效率也不高“ 这句话不是很赞同,在 https://cloud.tencent.com/developer/article/1164715 这篇文章有验证过,它比很多方法求幂都要高效。
python没有double型,但是pow用的是double型计算,存储double型数据的方式又和硬件非常相关,比较认同精度带来了结果差异
https://cloud.tencent.com/developer/article/1164715
math模块的pow和python内置pow - 成功解决问题
https://www.runoob.com/python/func-number-pow.html
语法
以下是 math 模块 pow() 方法的语法:
import math
math.pow( x, y )
内置的 pow() 方法
pow(x, y[, z])
函数是计算 x 的 y 次方,如果 z 在存在,则再对结果进行取模,其结果等效于 pow(x,y) %z。
注意:pow() 通过内置的方法直接调用,内置方法会把参数作为整型,而 math 模块则会把参数转换为 float。
发现一个新的使用技巧
返回 5 的 3 次方取余 4(等同于 (5 * 5 * 5) % 4):
x = pow(5, 3, 4)
含默认值的字典 - 计数器-有序列表
https://realpython.com/python-defaultdict/
############################################################
dep_d = dict()
for department, employee in dep:
dep_d.setdefault(department, []).append(employee)
############################################################
from collections import defaultdict
dep_dd = defaultdict(list) # set int float
for department, employee in dep:
dep_dd[department].append(employee)
############################################################
>>> from collections import Counter
>>> counter = Counter('mississippi')
>>> counter
Counter({'i': 4, 's': 4, 'p': 2, 'm': 1})
############################################################
>>> from sortedcontainers import SortedList
>>> l = SortedList()
>>> l.update([0, 4, 1, 3, 2])
>>> l.index(3)
3
>>> l.add(5)
>>> l[-1]
5