Python 如何用更省时的方法替换嵌套for循环?

Python 如何用更省时的方法替换嵌套for循环?,python,algorithm,Python,Algorithm,我给出了一个矩形,其左下和右上顶点坐标分别为(x1,y1)和(x2,y2)。一般点(x,y)在矩形外给出。并给出了一个整数值R 现在,我的目标是找到矩形上和内部的积分点总数,这些积分点与(x,y)的距离小于或等于R 我所做的是: n=0 for i in range(x1, x2+1, 1): for j in range(y1, y2+1, 1): if (i-x)**2+(j-y)**2<=R2: n+=1 print(n) n=0

我给出了一个矩形,其左下和右上顶点坐标分别为(x1,y1)和(x2,y2)。一般点(x,y)在矩形外给出。并给出了一个整数值R

现在,我的目标是找到矩形上和内部的积分点总数,这些积分点与(x,y)的距离小于或等于R

我所做的是:

n=0
for i in range(x1, x2+1, 1):
    for j in range(y1, y2+1, 1):
        if (i-x)**2+(j-y)**2<=R2:
            n+=1

print(n)
n=0
对于范围内的i(x1,x2+1,1):
对于范围(y1,y2+1,1)内的j:

如果(i-x)**2+(j-y)**2您可以将numpy用于矢量化暴力版本:

将numpy导入为np
P_x,P_y=-8,0
R=9
最小x_,最大x_=0,1
y_最小值,y_最大值=0,1
xx,yy=np.meshgrid(np.arange(x_最小,x_最大+1),np.arange(x_最小,x_最大+1))
距离=((xx-pux)**2+(yy-puy)**2)
打印(距离)

打印(np.sum)(距离对于矢量化暴力版本,您可以使用numpy:

将numpy导入为np
P_x,P_y=-8,0
R=9
最小x_,最大x_=0,1
y_最小值,y_最大值=0,1
xx,yy=np.meshgrid(np.arange(x_最小,x_最大+1),np.arange(x_最小,x_最大+1))
距离=((xx-pux)**2+(yy-puy)**2)
打印(距离)

打印(np.sum)(距离查找圆与矩形的交点

将交点类型分类为cap(圆线段)、扇形、无扇形的线段,可能还有其他类型

按Y坐标扫描,每个Y得到矩形和圆形内对应的最后一个X

X-edgeX
值添加到扇形交叉点的结果中。
edgeX
可能是x1或x2,具体取决于圆与哪个边相交

对于圆帽,取两个X点并将其差值相加


使用这种方法,复杂度与矩形大小成线性关系,但需要对交点进行分类。

找到圆与矩形的交点

将交点类型分类为cap(圆线段)、扇形、无扇形的线段,可能还有其他类型

按Y坐标扫描,每个Y得到矩形和圆形内对应的最后一个X

X-edgeX
值添加到扇形交叉点的结果中。
edgeX
可能是x1或x2,具体取决于圆与哪个边相交

对于圆帽,取两个X点并将其差值相加


使用这种方法,复杂度与矩形大小成线性关系,但需要对相交点进行分类。

通过将圆的离散点作为一系列直线来逼近,可以大大降低复杂度。使用这些直线,可以在无需计算时间的情况下,从数学上计算矩形相交点的数量嵌套循环。这将把复杂性从O(n^2)降低到O(n)

例如:

x1,y1 = (0,0)
x2,y2 = (1,1)
x,y   = (-8,0)
R     = 9

n = 0 
for cy in range(y-R,y+R+1):           # cy: vertical coordinate of circle's lines
    if cy not in range(y1,y2+1):          # no vertical intersection
        continue
    dx  = int((R**2-(cy-y)**2)**0.5)      # width of half circle at cy
    cx1,cx2 = x-dx,x+dx                   # edges of circle at line cy
    if cx2<x1 or cx1>x2: continue         # no horizontal intersection
    n += min(x2,cx2)-max(x1,cx1)+1        # intersection with cy line

print(n) # 3

通过将圆的离散点近似为一系列直线,可以大大降低复杂性。使用这些直线,可以在不使用嵌套循环的情况下,以数学方式计算与矩形相交的点的数量。这将使复杂性从O(n^2)降低到O(n)

例如:

x1,y1 = (0,0)
x2,y2 = (1,1)
x,y   = (-8,0)
R     = 9

n = 0 
for cy in range(y-R,y+R+1):           # cy: vertical coordinate of circle's lines
    if cy not in range(y1,y2+1):          # no vertical intersection
        continue
    dx  = int((R**2-(cy-y)**2)**0.5)      # width of half circle at cy
    cx1,cx2 = x-dx,x+dx                   # edges of circle at line cy
    if cx2<x1 or cx1>x2: continue         # no horizontal intersection
    n += min(x2,cx2)-max(x1,cx1)+1        # intersection with cy line

print(n) # 3

阅读列表理解嵌套列表理解同样会降低时间效率,不是吗?要获得更快的近似答案,您可以试试。@JoseKilo不,列表理解是有效的faster@Ethan不是真的…检查这个答案也许有一点改进,但在字节码级别,它们基本上是相同的。无论如何,OP是在问ab提高时间复杂度。阅读列表理解嵌套列表理解同样会降低时间效率,不是吗?要获得更快的近似答案,你可以试试。@JoseKilo不,列表理解是有效的faster@Ethan不是真的…检查这个答案也许有一点改进,但在字节码级别,它们本质上是同样。不管怎样,OP是在询问如何提高时间复杂度。