python - 降低python(2.7)算法的时间复杂度
问题描述
我输入了一个列表,该列表由三个列表组成,每个列表分别代表 X、Y 和 Z 坐标。例如:
coords = [[2, 1, 5, 2, 8, 6, 8, 6, 1, 2, 3 , 4], [1, 3, 4, 1, 2, 2, 2, 4, 2, 3, 4, 5], [2, 4, 7, 2, 1, 2, 1, 4, 5, 6, 9, 8]]
其中坐标 X 的列表是:X = [2, 1, 5, 2, 8, 6, 8, 6, 1, 2, 3 , 4]
一个点将像这样形成:point = [2, 1, 2]
。点 XYZ 表示立方体的一个顶点。(在我的程序中,我必须分析一组堆叠或并排的立方体)。
作为函数的输出,我想要一个与总点数一样大的 ID 列表(= 坐标列表之一的长度)。对于不同的点,ID 必须是唯一的,并且随着点列表的迭代而顺序递增。当一个点已经遇到时(例如,当一个立方体的顶点与另一个立方体的顶点重合时),在输出列表中,该点必须具有首先遇到相同点的 ID。
该示例的结果应该是outp = [1, 2, 3, 1, 5, 6, 5, 8, 9, 10, 11]
这是我编写的代码,它运行良好:
def AssignIDtoNode(coords):
outp = []
n_points = len(coords[0])
points = []
memo_set = set()
memo_lst = ["" for x in xrange(0, n_points)]
for i in range(n_points):
point = "(X = " + str(coords[0][i]) + ", Y = " + str(coords[1][i]) + ", Z = " + str(coords[2][i]) + ")"
if punto not in memo_set:
outp.append(i+1)
memo_set.add(point)
memo_lst[i] = point
else:
ind = memo_lst.index(point)
outp.append(ind+1)
return outp
当函数的输入中有一个非常大的点列表(数百万个点)并且计算时间显着增加时,就会出现问题。我已将每个点转换为一个字符串以方便搜索,并尽可能使用一组来减少第一次搜索时间。在我看来,程序需要通过 .index() 函数搜索某个点的索引时会花费很长时间。
有没有办法进一步优化这个功能?
解决方案
使用 enumerate、zip 和字典来存储索引 -{(x,y,z):index,...}
def f(coords):
d = {}
outp = []
for i,punto in enumerate(zip(*coords),1):
d[punto] = d.get(punto,i) # if it doesn't exist add it with the current index
outp.append(d[punto])
return outp
单次通过点,无类型转换,恒定时间查找。
>>> AssignIDtoNode(coords) == f(coords)
True
LBYL ...
def g(coords):
outp = []
d = {}
for i,punto in enumerate(zip(*coords),1):
if punto not in d:
d[punto] = i
outp.append(d[punto])
return outp
g
比f
100 万和 300 万 (x,y,z) 点快约 25%。
推荐阅读
- google-cloud-platform - 谷歌云存储传输
- ios - 如何在 iOS 图表的左轴上添加字符串?
- django - 没有调用mixin中的get_context_data
- authentication - 如何在 Java 中制作注册和登录示例并在不使用数据库语言的情况下存储注册记录?
- c# - 如何从 2 个不同的 Web 应用程序配置 WCF 设置
- c# - 使用约定时如何要求 FK?
- c# - ASCII 表和字符串
- android - 我可以为视图和附加到/具有约束关系的所有其他视图设置动画吗?
- python - 要合并的不同长度的 Python 时间序列数据集
- javascript - 仅在单击按钮时显示一个类