程序员数学 03:计数、增长与复杂度
“有两层循环,所以是平方复杂度”有时正确,有时不正确。更可靠的方法是明确输入规模
从两两比较数起
给
这是组合数
js
let comparisons = 0;
const n = 5;
for (let i = 0; i < n; i++) {
for (let j = i + 1; j < n; j++) comparisons++;
}
console.log(comparisons); // 10如果对象排列顺序重要且不允许重复选择,数量是
对数来自重复缩小
把候选范围每次减半,经过
但如果为了只查一次就先排序,排序成本也要算进去;如果容器不能高效定位中点,只数比较次数又不足以解释总成本。复杂度是基于操作成本假设的模型。
两层循环也可能是 n log n
js
let steps = 0;
const size = 8;
for (let i = 0; i < size; i++) {
for (let j = 1; j < size; j *= 2) steps++;
}
console.log(steps); // 24内层取 j++,才变成
O、Θ 与实测分别回答什么
这些符号不会告诉你具体运行几毫秒。常数、缓存、I/O、并行、运行时和数据分布都影响实际耗时。应同时写清最坏、平均还是摊还情况。例如哈希查找常用预期常数时间模型,但这不代表任意哈希实现、任意碰撞输入都保证最坏常数时间。
练习
- 20 个不同对象,不计顺序、不重复选取,选两个有几种方式?
- 先遍历
个元素,再遍历 个元素,是平方增长吗? - 一次准备成本为 1000 单位,每次查询从 10 降至 2 单位,至少查询多少次才比原方案严格便宜?
查看答案与讲解
。 - 不是,总次数
,是线性增长;“先后相加”不同于“每个外层都执行全部内层”。 - 要求
,所以 ,整数查询次数至少 126。这里假设每次查询成本固定,实际使用应测量。
资料与延伸
MIT 6.006 算法讲义 提供算法分析与数据结构材料。进一步学习时,把时间、额外空间和预处理成本分别列出来。
继续阅读
- 习题与解析
- 习题与解析
- 习题与解析