我在Python中有这个功能:
digit_sum = 0
while number > 0:
digit_sum += (number % 10)
number = number // 10
为了确定时间复杂度,我应用了以下逻辑:
第1行: 1个基本操作(分配),执行1次,因此获取值 1
第2行: 2个基本操作(读取变量'number'并与零比较),执行n + 1次,因此得到 2 *(n + 1)的值
第3行: 4个基本操作(读取变量'number',%10,计算总和和赋值),执行n次,得到值 4 * n
第4行: 3个基本操作(读取变量'number',// 10和赋值),执行n次,因此获得值 3 * n
这让我总共 1 + 2n + 2 + 4n + 3n = 9N + 3
但我的教科书有 8n + 3 的解决方案。我的逻辑在哪里出错?
谢谢,
亚历
答案 0 :(得分:2)
在谈论复杂性时,你真正关心的是asymptotic complexity。这里, O(n)。 8或9或42并不重要,特别是因为没有办法让你知道。
因此计算"操作"毫无意义。它暴露了底层处理器的架构细节(无论是实际的hw proc还是解释器)。真正获得真实"的唯一途径操作次数将是查看特定的实现(例如,比如CPython 3.6.0),并查看它从您的程序生成的字节码。
这是我的CPython 2.7.12所做的:
>>> def test(number):
... digit_sum = 0
... while number > 0:
... digit_sum += (number % 10)
... number = number // 10
...
>>> import dis
>>> dis.dis(test)
2 0 LOAD_CONST 1 (0)
3 STORE_FAST 1 (digit_sum)
3 6 SETUP_LOOP 40 (to 49)
>> 9 LOAD_FAST 0 (number)
12 LOAD_CONST 1 (0)
15 COMPARE_OP 4 (>)
18 POP_JUMP_IF_FALSE 48
4 21 LOAD_FAST 1 (digit_sum)
24 LOAD_FAST 0 (number)
27 LOAD_CONST 2 (10)
30 BINARY_MODULO
31 INPLACE_ADD
32 STORE_FAST 1 (digit_sum)
5 35 LOAD_FAST 0 (number)
38 LOAD_CONST 2 (10)
41 BINARY_FLOOR_DIVIDE
42 STORE_FAST 0 (number)
45 JUMP_ABSOLUTE 9
>> 48 POP_BLOCK
>> 49 LOAD_CONST 0 (None)
52 RETURN_VALUE
我让你得出自己想要实际算作基本操作的结论。 Python解释器一个接一个地解释字节码,所以可以说你有15"基本操作"在你的循环中。这是你能得到一个有意义的数字的最接近的。尽管如此,那里的每个操作都有不同的运行时间,因此15没有任何有价值的信息。
另外,请记住这是CPython 2.7.12特有的。很可能另一个版本会生成其他版本,利用新的字节码可能会以更简单的方式表达某些操作。