Python 如何用更省时的方法替换嵌套for循环?
我给出了一个矩形,其左下和右上顶点坐标分别为(x1,y1)和(x2,y2)。一般点(x,y)在矩形外给出。并给出了一个整数值R 现在,我的目标是找到矩形上和内部的积分点总数,这些积分点与(x,y)的距离小于或等于R 我所做的是: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
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是在询问如何提高时间复杂度。