leetcode 223. 矩形面积 - 850. 矩形面积 II - 坐标投影 -线段覆盖 - 有效区间计算 -pow 指数计算 -含默认值的字典-有序列表-counter

本文探讨了如何计算两个轴对齐矩形的覆盖面积,包括基本算法和优化策略。针对大范围内的精度问题,文章指出在计算时不应依赖`math.pow()`,推荐使用内置的`pow()`函数。此外,还介绍了利用有序列表和默认值字典来优化数据结构的技巧。
摘要由CSDN通过智能技术生成

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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值