javascript - 如果它仅取决于输入值而不是输入大小,如何确定 Big-o 复杂度?
问题描述
我刚刚看到了关于排序的javascript代码setTimeout
,如图所示
var list = [2, 5, 10, 4, 8, 32];
var result = [];
list.forEach( n => setTimeout(() => result.push(n), n));
这很有趣,因为在 jssetTimeout
中是异步的,所以如果你等待足够的时间,result
就会对数组进行排序。它是确定性的,仅取决于数据的值,而不取决于输入的大小,所以我不知道如何确定这种方法的 Big-O(时间复杂度)。
解决方案
TLDR;这取决于你如何定义复杂性setTimeout()
在讨论算法复杂性时,我们必须回答以下问题:
- 我的输入是什么?
- 我的算法运行的假设机器中的工作单元是什么?
在某些情况下,我们如何定义输入取决于算法在做什么以及我们如何定义我们的工作单元。使用内置函数时问题很复杂,因为我们必须定义这些函数的复杂度,以便我们可以将它们考虑在内并计算算法的整体复杂度。
的复杂度是setTimeout()
多少?这有待解释。我发现给出setTimeout()
的复杂度很有帮助O(n)
,其中n
是传递给函数的毫秒数。在这种情况下,我决定内部计算的每一毫秒setTimeout()
代表一个工作单位。
鉴于它setTimeout()
具有复杂性O(n)
,我们现在必须确定它如何适应我们算法的其余部分。因为我们正在循环list
调用setTimeout()
列表的每个成员,所以我们乘以n
另一个变量,让我们调用它k
来表示列表的大小。
综上所述,该算法具有复杂性O(k * n)
,其中k
是给定数字的长度,并且n
是列表中的最大值。
这种复杂性有意义吗?让我们通过解释我们的分析结果来进行健全性检查:
- 我们的算法需要更长的时间,因为我们给它更多的数字✓</li>
- 我们的算法需要更长的时间,因为我们给它更大的数字 ✓</li>
请注意,这个结论的关键是确定 的复杂性setTimeout()
。如果我们给它一个恒定的O(1)
复杂性,我们的最终结果将是O(k)
,IMO 具有误导性。
编辑:
也许对所有输入setTimeout()
的贡献更正确的解释是给定列表的最大值,无论它被调用多少次。O(n)
n
在原始帖子中,我假设列表中的每个项目setTimeout()
都会运行时间,但是这个逻辑在概念上“缓存”以前的值有一点缺陷,所以如果用 调用它,它将运行 100 个工作单元(如反对 180 个工作单元,这是原始帖子中的情况)。n
setTimeout()
setTimeout(30), setTimeout(50), and setTimeout(100)
鉴于对 的这种新的“缓存”解释setTimeout()
,复杂度为O(k + n),其中k
是列表的长度,并且n
是列表中的最大值。
有趣的事实:这恰好与Counting Sort 具有相同的复杂性,其复杂性也是列表大小和最大列表值的函数
推荐阅读
- regex - 如何过滤一组路径以避免使用 AWK 重复它们?
- c# - Parallax 工作,但 PARALLAX 中的 ListView 不起作用 - Xamarin Forms
- c++ - 在 C++17 中定义可变坐标(元组)类型?
- angular - 在 Angular 应用程序中存储 JWT 的标准做法是什么?
- python - Tkinter GUI 重叠或刷新列表中的标签
- jsf - 如何构建动态网格并在一行中只显示三列(JSF 2.2 和 BootsFaces)
- excel - VBA - 如何引用两个单独的打开工作簿而不命名它们?
- redis - 您如何获得流列表?
- sql - 加入表格并选择最大日期
- javascript - Rails 动态 collection_select 仅过滤大约 50% 的时间