我正在研究一个leet问题,我只是为了好玩而已。我认为我可以深入探讨该问题的所有测试输入。可以这么说,我提前知道所有输入。返回解决方案最快的结构是什么。
我尝试使用字典将所有输入与假定的解决方案进行映射。
class DictSolution():
DATA = {x:x for x in range(1000000)}
def compute(self, x):
return self.DATA[x]
然后,我想,因为我知道输入将按什么顺序进行测试,所以我不需要“查找”。因此,我尝试使用set
并忽略所有输入。
class SetSolution():
DATA = {i for i in range(1000000)}
def compute(self, x):
return self.DATA.pop()
令我惊讶的是,它比dict
慢一点,每次都慢1-2%。顺便说一句,这是我给他们计时的方式。
def test_dict():
sol = DictSolution()
for i in range(1000000):
sol.compute(i
ds = timeit.timeit(test_dict, number=1)
ss = timeit.timeit(test_set, number=1)
print ("Dict Solution:", ds)
print ("Set Solution:", ss)
>> Dict Solution: 0.11734077199999998
>> Set Solution: 0.11939082499999998
问题:
set
慢一些?dict
方法已经是最快的方法。我该怎么做才能获得更好的时间?答案 0 :(得分:1)
我相信@schwobaseggl的建议是正确的。从here开始,O(1)
和dict
的访问元素的复杂度均为list
,实际上在之前的question中已对此进行了复制设置list
比dict
更快。我完全复制了您的基准,并添加了其他数据结构:
代码:
import timeit
from collections import deque
class DictSolution:
DATA = {x: x for x in range(1000000)}
def compute(self, x):
return self.DATA[x]
class SetSolution:
DATA = {i for i in range(1000000)}
def compute(self, x):
return self.DATA.pop()
class DequeSolution:
DATA = deque(i for i in range(1000000))
def compute(self, x):
return self.DATA.popleft()
class ListSolution:
DATA = [i for i in range(1000000)]
def compute(self, x):
return self.DATA[x]
class TupleSolution:
DATA = tuple(i for i in range(1000000))
def compute(self, x):
return self.DATA[x]
def test_dict():
sol = DictSolution()
for i in range(1000000):
sol.compute(i)
def test_set():
sol = SetSolution()
for i in range(1000000):
sol.compute(i)
def test_deque():
sol = DequeSolution()
for i in range(1000000):
sol.compute(i)
def test_list():
sol = ListSolution()
for i in range(1000000):
sol.compute(i)
def test_tuple():
sol = TupleSolution()
for i in range(1000000):
sol.compute(i)
def test_pop_list():
sol = PopListSolution()
for i in range(1000000):
sol.compute(i)
des = timeit.timeit(test_deque, number=1)
ss = timeit.timeit(test_set, number=1)
ds = timeit.timeit(test_dict, number=1)
ls = timeit.timeit(test_list, number=1)
ts = timeit.timeit(test_tuple, number=1)
times = [("Dict Solution:", ds), ("Set Solution:", ss), ("Deque Solution:", des), ("List Solution:", ls), ("Tuple Solution:", ts)]
for label, time in sorted(times, key=lambda e: e[1]):
print(label, time)
输出
Tuple Solution: 0.1597294129896909
List Solution: 0.16653884798870422
Dict Solution: 0.17414769899914972
Set Solution: 0.190879073983524
Deque Solution: 0.1914772919844836
我多次运行了脚本,结果与元组解决方案和列表解决方案交替使用的结果相似。请注意,SetSolution
和DequeSolution
都是最慢的。因此,回答您的问题:
set
和deque
都较慢,因为您要从列表中删除一个元素,而在其他结构中,您仅访问这些元素。 注释
尽管pop
与set
一起用于测试用例,但是通常不会出现这种情况,例如:
test = {'e' + str(i) for i in range(10)}
while test:
print(test.pop())
输出(弹出设置)
e5
e8
e6
e0
e1
e3
e7
e4
e9
e2
有关该主题的更多信息,请参见here。
我还使用list.pop(0)
对解决方案进行了基准测试,尽管使用的范围较小:100000
,并且候选对象(列表,元组和字典)更少。结果如下:
('List Solution:', 0.018702030181884766)
('Tuple Solution:', 0.021403074264526367)
('Dict Solution:', 0.02230381965637207)
('List Pop Solution', 1.8658080101013184)
该基准测试是在以下设置上运行的:
Intel(R) Core(TM) i7-4500U CPU @ 1.80GHz
16GB
Ubuntu 16.04
Python 3.5.2
答案 1 :(得分:0)
dict是最快的查找数据结构,因为它是使用哈希表实现的:在哈希表中查找键几乎需要固定的时间。请查看下面的链接以获取更多信息: