其实是道大模拟题目。
题目分析:
时间复杂度介绍:
时间复杂度是衡量算法运行时间随输入规模增长的变化趋势,用大 OOO 符号表示,忽略常数项和低阶项,只关注最高阶项的增长量级 。————百度百科
而这道题保证表示时间复杂度的只有 O(1)O(1)O(1) 和 O(nk)O(n^k)O(nk) 两种类型。
如何判断时间复杂度为 O(1):
看程序中是否存在一层能够执行、并且循环次数随 n 增长的循环。
如果不存在这样的循环,那么程序的时间复杂度就是 O(1)O(1)O(1)。
如何判断时间复杂度为 :
看程序中是否存在一层能够执行、并且循环次数随 nnn 增长的循环。
如果最大有效嵌套层数是 1,那么时间复杂度就是 O(n)O(n)O(n)。
同理如果嵌套层数是 2 则为O(n2)O(n^2)O(n2),嵌套层数是 3 则为O(n3)O(n^3)O(n3),以此类推。
以下是各个循环对时间复杂度的贡献值,用的数是举例,可借此延伸到其它同类型的数。
循环形式 循环次数 复杂度 F i 1 10 固定次数 O(1)O(1)O(1) F i 1 n 随 nnn 增长 O(n)O(n)O(n) F i n 10 一次也不执行 不执行 F i n n 执行一次 O(1)O(1)O(1)
代码思路:
对于循环语句 F i x y,我用了变量***来判断对时间复杂度的贡献。
循环条件 d 的值 含义 对复杂度的贡献 x 是整数,y 是 n 1 循环大约执行 nnn 次 增加一阶 x 是 n,y 是整数 -1 循环一次也不执行 不贡献复杂度,并使内部循环失效 两者都是整数,且 x > y -1 循环一次也不执行 不贡献复杂度,并使内部循环失效 两者都是整数,且 x <= y 0 循环执行常数次 不增加复杂度 两者都是 n 0 循环执行常数次 不增加复杂度
例如:
两层循环都贡献一阶,因此时间复杂度是 O(n2)O(n^2)O(n2)。
第一段执行约 nnn 次,第二段也执行约 nnn 次。
总次数约为 n+n=2nn+n=2nn+n=2n,因此复杂度仍然是 O(n)O(n)O(n),而不是 O(n2)O(n^2)O(n2)。
雷点:
外层循环根本不执行,因此内部循环即使看起来是 O(n)O(n)O(n),整个程序仍然是 O(1)O(1)O(1)。
雷点分析:如果某一层循环永远不执行,它内部所有循环对整个程序的复杂度都没有贡献。
所以要用一个flagflagflag标记来辅助判断。
检查语法错误
1.1.1.F 和 E 不匹配,例如少写一个 E,或者多写一个 E。
2.2.2.变量重复定义,例如外层变量 x 尚未销毁,又在内层定义 x。
雷点:即使错误出现在无法执行的循环中,也必须判定为 ERR。
所以需要:
1.1.1.用栈匹配 F 和 E。
2.2.2.用变量标记记录哪些变量仍然处于使用状态。
最后比较复杂度然后输出
假设分析得出的实际复杂度是 O(na)O(n^a)O(na),题目给出的复杂度是 O(nb)O(n^b)O(nb)。
按一下顺序判断并输出:
1.1.1.如果有语法错误,输出 ERR。
2.2.2.如果没有语法错误,且 a=b,输出 Yes。
3.3.3.如果不满足以上任何情况,输出 No。
整个解题流程
读取题目给出的复杂度 → 逐行读取循环,判断循环类型 → 利用栈处理嵌套,统计最大有效增长层数 → 检查变量重名和 F、E 是否匹配 → 有语法错误输出 ERR;否则比较指数,输出 Yes 或 No。
总结:用栈处理嵌套,用变量标记检查语法错误,用最大有效增长循环层数计算复杂度,最后比较指数。
重点:这道题的关键不是计算循环具体执行多少次,而是判断哪些循环有效,以及它们最多有多少层真正嵌套执行。
终于写完了
AC CODE