O(n) 要求您首先定义“n”可能是什么。说,任务是:
给定一个大小为 t 的整数数组 a 和一个特定整数 x,返回x在a中出现的第一个索引>;如果 x 不在 a 中,则返回 -1。
然后,我想到了这个算法:
for (int i = 0; i < a.length; i++) if (a[i] == x) return i;
return -1;
这个算法是O(t)。
这是什么意思?
好吧,做一个图表。在 x 轴上,放置“所用时间”(或所用内存;您可以根据需要测量空间复杂度或时间复杂度)。在 y 轴上,输入“t”:该数组的大小。
现在,开始运行您的算法。首先是一个 1 大小的数组,然后是一个 2 大小的数组,然后继续。最终是一个百万大小的数组。把它画出来。
在 0 点附近(小阵列)到处都是。 wild 摆动 - 你更多地测量 JVM 启动时间,你的音乐播放器是否正在切换到下一首曲目,你的浏览器是否在做一些工作,谁知道呢。一团糟。但最终这条线会稳定下来。一旦您的输入数组中有几百万个项目,热点启动、VM 预热、音乐播放器 - 这些都不再对测量产生有意义的影响。
一旦线路稳定下来,它会是什么样子?
O(n) 算法说:“它看起来像一条非水平直线”。因为如果你绘制y = C*x,(为C选择任何常数),那看起来就像一条非水平直线。
O(1) 算法看起来像一条水平线(为什么?因为 y = C 看起来像那样)。 O(n^2) 算法看起来就像 y = x^2 所做的那样,如果你绘制它,等等。就像y = 812398x^2 + 234124124x 最终看起来几乎和y = x^2 一样,只要你“向右走得足够远”,在O(x) 表示法中,常数因子和黯然失色的因子(812398 是常数,234124124x部分黯然失色)被忽略。这是关于“图表最终会是什么样子?”,而这些方面根本不会影响这一点。
现在您知道O(n) 的含义了。然后解释为什么这个算法是O(n) 是微不足道的:如果你的数组中有一百万个数字,你必须查看潜在的一百万个条目来找出答案。谁告诉你它是O(1) 是错误的,或者你更有可能听错了。也许他们在谈论:
为这个任务提供一些优化的集合,确定给定整数 x 是否在数据结构 a 中有多难?里面有 t 个元素吗?
对于数组,答案是O(n),但如果a 是HashSet,答案是O(1)。哈希集不需要检查每个元素。