计算机的问题求解方法
看完你能把一个真实问题一步步拆成计算机可执行的程序
按 空格/→ 演示下一步
全部页面点击任意一页,跳回舞台从这页播放
计算机的问题求解方法
看完你能把一个真实问题一步步拆成计算机可执行的程序
程序设计面向的问题
上一页说,计算机解题靠把问题拆成一步步执行。但不是所有问题都能这么拆——有些问题再快的机器也算不出来。那什么样的题才值得交给它?得连过三道关。
菜谱写得足够明确,才能让完全不懂做菜的人照做成功
求解路径总览
前面说了计算机擅长解决什么问题,但拿到一个问题,从想法到能跑的程序并不是一步到位的。就像做菜:先想吃什么、再定菜谱、写成步骤卡、最后下锅。这个过程拆开正好四步。
定吃什么对应问题分析,定菜谱对应算法设计,写步骤卡对应算法表示,下锅对应程序实现
什么是计算
前几页我们梳理了求解路径,但有个更根本的问题:计算机到底在做什么?你以为它只会算 3+4=7?其实按规则改动符号这件事,都是计算。
菜谱的步骤对应规则,食材对应符号,成品就是输出
冯·诺依曼结构与可计算性
上一页说「计算」是把输入变输出。可机器怎么知道下一步做什么?想想菜谱:步骤和食材写在同一张纸上,厨师照着逐条做——冯·诺依曼把这个思路搬进了计算机。
菜谱上的步骤对应指令,食材对应数据,都在内存中
计算模型的边界
从左往右读:任何问题先问能否给出算法,答案决定了它落在可计算或不可计算哪一侧。
算法:解决问题的步骤
做红烧肉时菜谱会写:切块、焯水、加糖炒色、炖四十分钟——步骤有限、每步说得清、谁照着做都能执行。算法就是这种「照做就能解决」的步骤序列的正式名字。
菜谱的步骤对应算法操作,菜对应输出结果
算法特征:有穷性与确定性
很多人把算法等同于菜谱,但菜谱在两个关键点上并不合格——这正是算法定义的边界所在。
- “炒至金黄”无判定标准,依赖厨师经验
- “适量”“少许”,用量无法精确执行
- 步骤可能失败收场,不保证产出结果
- 每步操作有唯一解释,任何执行者结果一致
- 输入、每步规则完全明确,无模糊词
- 对合法输入必定终止并输出确定结果
算法特征:可行性、输入与输出
前两页我们确认了算法要「走得完、走得准」。但菜谱里若写「撒上一撮运气」,厨师照样卡壳——每一步都得真做得了。同时菜谱要食材、要端出成品,算法也讲究进出。
菜谱步骤须可操作对应可行性;食材对应输入;端出的菜对应输出
自测:这算算法吗
这段“泡茶步骤”不满足算法的哪些特征?
自然语言表示
前面说算法必须确定性、无歧义。那最顺手的方式——直接用中文把步骤写下来行不行?试试「找出这组数里最大的那个」,每个人理解一样吗?
传话每转一次意思就偏一点,算法容不得这种偏差
流程图表示
用流程图的三种符号画出三种控制结构:椭圆是起点终点,菱形是判断分支,箭头是流程线,顺着箭头读执行路径。
伪代码与 N-S 图
自然语言描述算法容易有歧义,流程图画起来又慢又占地方。有没有折中方案?工程师用了一套接近代码、又不受具体语言语法约束的书写方式——伪代码,配合 N-S 图,让算法一步步逼近真正的程序。
草图画结构与布局,不必标注每种材料;代码才是施工图
从伪代码到 C 程序
同一算法的三级表示:伪代码如何逐行落地为可编译运行的 C 程序。
伪代码的每一步都能在 C 中找到唯一对应:变量声明补上类型,循环与累加原样落地,最后用格式化输出得到 5050。
为什么算法要优化
同一道题,你写的程序 1 秒出结果,同学的跑了半小时还没停。都能得到答案,差别在哪?前面我们确认了算法必须正确,现在看另一个维度:算得对,和算得好,是两回事。
都能到家,但堵车的绕远路对应效率低下的算法
优化实例:求和与查找
同一问题常有多种解法,朴素解法正确但慢;改进解法好在哪、边界在哪,值得逐项对照。
- 求和:逐项累加 1 到 n
- 查找:从头到尾逐个比对
- 时间随规模线性增长 O(n)
- 求和:用公式 n(n+1)/2 一次算出
- 查找:有序数据折半,每次砍一半
- 对数级 O(log n),常数级 O(1)
优化的思路
算法优化不是一步登天,而是沿固定路径逐级推进。
自顶向下逐步求精
上一页我们优化了求和与查找,靠的是换思路。可问题一大,思路就不够用了——做一桌年夜饭没人会同时炒所有菜,先定菜单,再分到每道菜,这正是自顶向下的做法。
菜单对应总目标,每道菜对应子模块,具体步骤对应代码
三种基本控制结构
图中有三条支路:直线是顺序,菱形分岔是选择,带回边的路径是循环,箭头汇合处表示任何算法都能由它们拼成。
模块化与 C 语言落地
看一个自顶向下设计的完整落地:求和任务拆成函数,每个函数负责一件事。
sum、report 各自封装一步求精,main 是顶层调度——这就是自顶向下在 C 里的样子:层层分解成函数,main 只管调用。
从问题到程序的完整闭环
- ✓问题先变成可计算的问题,才轮得到计算机出场
- ✓算法是核心:有穷、确定、可行,缺一不可
- ✓同一问题解法差异巨大,优化比写出答案更重要
- ✓表示只是桥梁:自然语言到 C,语义不能走样
- ✓自顶向下求精加模块化,复杂度被分而治之
课后思考
先合上讲义自己想几分钟,再看参考答案,核对思路方向。
参考答案从定义看它不满足有穷性,更接近'服务过程'而非'一次求解'。想一层:如果把'处理一次事件'拆成单轮,每一轮是否有穷、确定?边界在于我们给算法划的'一次求解'范围。
参考答案先别想代码,先用一句话写出最终目标,再问'它依赖哪几个子结果'。对照第 20 页的闭环:问题→算法→程序,拆到每个子问题都能用三种基本结构描述为止。
参考答案不可计算指'不存在算法一步步机械求解',不等于无解——有些问题靠人的洞察、数学证明或限定条件后可解。思考:可计算性是'方法的边界',不是'答案的边界'。