【问题标题】:When i measure the running time of an algorithm that should be of O(n) = n, i am getting O(n) = 1. What am i doing wrong?当我测量应该为 O(n) = n 的算法的运行时间时,我得到 O(n) = 1。我做错了什么?
【发布时间】:2021-08-04 07:48:12
【问题描述】:

我正在自学数据结构,我正在尝试测量将 append 方法实现到数组数据结构的高效和低效方式之间的时间复杂度差异。也就是说,根据我在纸上所做的一些数学运算,低效的方式应该是 O(n) = n^2,而有效的方式应该是 O(n) = n。

问题是,当我运行模拟并在图表上绘制这两种情况时,低效的方式按预期执行,但有效的方式执行 O(n) = 1。我做错了什么吗?

import datetime
import time
import random
import matplotlib.pyplot as plt
import numpy as np

# Inefficient append
class PyListInef:
   
   
   def __init__(self):
       self.items = []
   
   def append(self, item):
       # Inefficient append -> appending n items to the list causes a O(n) = n^2, since for each i for i in 1, 2, 3...n 
       # we need i * k operations in order to append every element to the new list. Then, by weak induction we prove 
       # that the number of required operations is n(n+1)/2 which implies O(n) = n^2
       self.items = self.items + [item]
       
   # Using magic method for our PyList to be an iterable object.
   def __iter__(self):
       for c in self.items:
           yield c
           
# Efficient append:

class PyList:
   def __init__(self):
       self.items = []
   
   def append(self, item):
       self.items.append(item)
   
   def __iter__(self):
       for c in self.items:
           yield c

# The inefficient append running time

lst = PyListInef()

time_dict_inef = dict()
time_dict_ef = dict()

series = np.linspace(1, 301, 300)

   
time.sleep(2)
   
for i in range(300):
   starttime = time.time()
   for j in range(i):
       lst.append(series[j])
       
   elapsed_time = time.time() - starttime
   time_dict_inef[i] = elapsed_time * 100000
   
# The efficient append running time

lst = PyList()

time.sleep(2)

for i in range(300):
   starttime = time.time()
   for j in range(i):
       lst.append(series[j])
       
   elapsed_time = time.time() - starttime
   time_dict_ef[i] = elapsed_time * 100000

plt.figure(figsize = (14,7))
plt.plot(time_dict_inef.keys(), time_dict_inef.values())
plt.plot(time_dict_ef.keys(), time_dict_ef.values())
plt.xlabel('Number of elements to append')
plt.ylabel('Elapsed time (microseconds)')
plt.title('Comparison between efficient appending vs inefficient appending in a list data structure')
plt.show()

你能帮我指出我做错了什么吗?

【问题讨论】:

  • 不要计时单次运行,而是尝试计时 100/1000 次运行?
  • 使用更高的 n,例如 1,10,100,1000,10000,10000 由于系统开销、设置时间等原因,几微秒的计时大多是无用的......
  • 我会努力做到的!!谢谢大家。

标签: python arrays algorithm data-structures big-o


【解决方案1】:

time.time() 的分辨率有限。您的“高效追加”时间足够快,它们通常在time.time() 的分辨率的一个滴答声之前完成。请注意黄色图表中究竟出现了两次:0 个滴答声和 1 个滴答声。图表右侧的 1-tick 时间更频繁,因为即使时间短于单个滴答,时间越长意味着在运行时发生滴答的概率越高。如果您使用更大的输入运行,您最终会看到 2-tick 时间甚至更高。 (另请注意,100000 中没有足够的 0,因此您的时间差了 10 倍。)

【讨论】:

  • 非常感谢,user2357112支持莫妮卡!我刚刚注意到缺少的 0 哈哈。现在是我所在时区的凌晨 2 点,我有点累了。我想是时候睡觉了。您知道是否有针对 time.time() 的限制的解决方法,以便测量有效函数并获得类似于直线的东西?
猜你喜欢
  • 1970-01-01
  • 2013-12-28
  • 1970-01-01
  • 2015-05-25
  • 2015-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多