如何解决复杂度与运行时的实际增长不匹配吗?
我已经做了一段时间的作业表了,我认为无症状复杂性与运行时结果表明之间存在巨大差异。
下面是程序运行时的表。
| Input Size | Runtime (Seconds) |
|---------------------|-------------------------|
| 10000 | 0.040533803 |
|---------------------|-------------------------|
| 20000 | 0.154712122 |
|---------------------|-------------------------|
| 30000 | 0.330814060 |
|---------------------|-------------------------|
| 40000 | 0.603440983 |
|---------------------|-------------------------|
| 50000 | 0.969272780 |
|---------------------|-------------------------|
| 60000 | 1.448454467 |
string = "";
newLetter = "a";
for (int i = 500; i < n; i++) {
string = string + newLetter;
}
return string
除了我错了,为什么算法的复杂性和运行时间的增长之间会有差异?
从运行时结果看,该程序的时间复杂度为O(n 2 )。输入大小加倍似乎将运行时间增加了4倍,这暗示二次函数?
但是从程序本身来看,我可以确定99.9%的时间复杂度实际上是O(n)。
这种差异是否有其他原因?运行时结果确实可能是线性的吗?
对于这种差异,我最好的猜测是for循环会使下一次迭代变慢(这对程序而言是有意义的,因为我认为Java编译器必须迭代给定的每个其他newLetter),但仍然是线性的。 ?它不是嵌套的for循环。
解决方法
您编写的代码实际上确实在时间Θ(n 2 )中运行。原因与这部分代码有关:
string = string + newLetter;
在这里,您的意图是说“请在此字符串的末尾附加一个新字符”。但是,Java实际执行的操作如下:
- 计算表达式
string + newLetter
。这将形成一个全新的字符串,该字符串是通过复制string
的全部内容,然后将newLetter
附加到该新字符串的末尾而形成的。 - 将结果分配给
string
。
这里的问题是,步骤(1)花费的时间越长,字符串的执行时间就越长,因为必须复制所有字符。特别地,如果string
的长度为k
,则步骤(1)花费时间Θ(k),因为必须复制k个字符。由于string
的长度与当前循环迭代索引匹配,因此这意味着完成的工作
Θ(1 + 2 + 3 + ... + n)
=Θ(n(n + 1)/ 2)
=Θ(n 2 ),
这就是为什么您看到自己所看到的情节。
您可以通过使用StringBuilder
而不是String
来组装较大的字符串来加快速度。它并不会制作所有中间副本,而是维护一个可以根据需要增长的内部数组。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。