
该函数将整数转为罗马数字,虽输入范围限定在 1–3999,但时间复杂度应按输入值 n 的增长趋势分析,而非固定上限;其核心循环次数与 num 成线性关系,故正确渐近复杂度为 o(n)。
该函数将整数转为罗马数字,虽输入范围限定在 1–3999,但时间复杂度应按输入值 n 的增长趋势分析,而非固定上限;其核心循环次数与 num 成线性关系,故正确渐近复杂度为 o(n)。
在算法分析中,时间复杂度描述的是当输入规模趋于无穷时,运行时间的增长趋势,而非仅考察实际约束下的有限取值。尽管题目中明确限制 1 ≤ num ≤ 3999,这一硬性上界看似支持“最多执行固定次数”的直觉(如最坏情况约 3999 次减法),但复杂度分析的对象是算法本身所依赖的输入变量,而非外部业务约束。
观察核心逻辑:
for (let i = 0; i = romanNumerals[i][0]) {
result += romanNumerals[i][1];
num -= romanNumerals[i][0]; // 每次至少减去 1
}
}
内层 while 循环的总执行次数,等于所有被减去的数值之和——而该和恰好等于原始输入 num(因为每次减法均从 num 中扣除一个面值,最终 num 归零)。例如:
- num = 8 → "VIII" → 执行 4 次加法(V + I + I + I),对应 4 次 num -= ...
- num = 3999 → 最多需约 3999 次单位减法(极端全用 "I" 表示时),实际因贪心策略使用大面值会显著减少,但仍与 num 呈线性正相关
因此,设输入为 n,则总操作数(字符串拼接 + 减法)满足:
c₁·n ≤ T(n) ≤ c₂·n(其中 c₁, c₂ 为常数,由面值表结构决定),即 T(n) ∈ Θ(n),故时间复杂度为 O(n)。
⚠️ 常见误区辨析:
- ❌ “因为数组长度固定(12 项),所以是 O(1)” —— 错误。外层 for 是 O(1),但内层 while 的总迭代次数随 num 线性增长,主导整体复杂度。
- ❌ “3999 是常数,所以 O(1)” —— 混淆了问题实例约束与渐近分析模型。若将输入域视为 {1,2,…,3999},则任何算法在此有限集上都是 O(1),但这丧失了算法分析的意义——我们关心的是 当输入可任意增大时,性能如何变化。
✅ 正确视角:
将 num 视为可扩展的输入规模参数(即使题目限制了范围,分析仍应基于其数值大小),则该算法是典型的伪线性时间算法(pseudo-linear):它对数值型输入呈线性依赖,而非对输入的二进制位长(即 log n)依赖。严格来说,若以输入长度(bit 数)为尺度,其复杂度实为 O(2^b),属指数级——但本题上下文默认以 num 的数值大小为规模度量,故标准答案为 O(n)。
总结:算法的时间复杂度由其最主导的、随输入增长而增长的部分决定。此处 num 的数值大小直接控制循环总次数,因此答案是 O(n),而非 O(1)。











