Python 练习讲解 · 25 / 25

算法是什么:同一问题的两种解法

算法是一组明确、有限的步骤,用输入得到所需输出。

要学习的知识点

题目

补充练习:理解算法的输入、确定步骤、有限性和输出。

输入非负整数 n;分别用循环算法和公式算法计算 1+...+n,并比较结果与操作次数。

参考程序:ex25.py;空白练习:lx25.py。

完整代码

以下内容与 ex25.py 一致,可对照右侧讲解阅读。

"""补充练习:理解算法的输入、确定步骤、有限性和输出。
输入非负整数 n;分别用循环算法和公式算法计算 1+...+n,并比较结果与操作次数。

学习说明:
- 输入是 n,输出是从 1 到 n 的整数和;n=0 时总和为 0。
- 循环算法的步骤明确,每次累加一个数;循环次数有限,为 n 次。
- 公式算法使用 n*(n+1)//2,运算步骤数不随 n 增长。
- 两种算法计算同一结果,比较它们可以帮助理解算法设计和效率。
"""
n = int(input())
if n < 0:
    raise ValueError("n 必须为非负整数")

# 循环算法:步骤明确,每次将下一个整数加入总和,执行有限次。
loop_total = 0
for value in range(1, n + 1):
    loop_total += value

# 公式算法:使用等差数列求和公式,常数次算术运算得到结果。
formula_total = n * (n + 1) // 2
print("loop result and additions:", loop_total, n)
print("formula result:", formula_total)
print("results match:", loop_total == formula_total)

进阶写法

这版与初学版解决同一道题,使用更精炼的语法或标准库工具。

进阶源码:ex25_adv.py

"""练习 25 进阶版:用 sum 和 range 计算循环累加结果。"""
n = int(input())
if n < 0:
    raise ValueError("n 必须为非负整数")

loop_total = sum(range(1, n + 1))
formula_total = n * (n + 1) // 2
print("loop result and additions:", loop_total, n)
print("formula result:", formula_total)
print("results match:", loop_total == formula_total)

sum(range(1, n+1)) 用内置求和计算循环累加结果,range() 提供 1 到 n;公式部分用固定次算术运算计算。

运行结果

示例输入:

10

程序输出:

loop result and additions: 55 10
formula result: 55
results match: True

逐个认识函数

下表根据程序中实际调用的函数和方法整理;自定义函数的实现与算法细节见后续说明。

函数形式功能与返回值注意事项
ValueError(message)内置异常类型,用来表示参数值不符合要求。raise ValueError(...) 会立即抛错并停止当前程序流程。
input(prompt='')读取一行文本,返回 str;若提供 prompt 会先显示提示。返回值默认是字符串,计算前通常要做类型转换。
int(value, base=10)把整数文本或数值转换为整数。int('3.5') 不合法;按指定进制解析时可传 base。
print(*objects, sep=' ', end='\n')把对象转换为文本显示;返回 None。默认空格分隔并在末尾换行。
range(start, stop, step=1)产生整数序列供循环或索引使用。stop 不包含在序列里。

算法的几个特点

  • 有输入:本题输入 n。
  • 有输出:本题输出总和以及两种结果是否相同。
  • 步骤明确:循环每次把当前整数加到总和;公式明确是 n(n+1)/2。
  • 有限性:循环从 1 到 n,有限次后结束。
  • 有效性:对题目允许的输入,步骤能得到正确结果。

两种算法如何运行

循环累加

loop_total = 0
for value in range(1, n + 1):
    loop_total += value

初始总和是 0。n=4 时依次变为 1、3、6、10。循环次数是 n,时间量级 O(n)。

等差数列公式

formula_total = n * (n + 1) // 2

把首尾配对:1+n、2+(n-1),每对都等于 n+1。所有数的总和是 n(n+1)/2。该写法用固定次数的算术运算,时间量级 O(1)。整数除法 // 可确保得到整数。

代码中的函数和运算

函数/写法参数与返回值说明
input()读入一行,返回字符串。与 int 配合得到 n。
int(text)把整数文本转换为 int。输入非整数文本会产生 ValueError。
range(1, n + 1)生成整数序列 1 到 n。停止位置不包含在序列中,因此写 n+1。
+=累加赋值,更新变量本身。loop_total += value 等价于总和加上 value 后再保存。
==比较是否相等,返回 bool。检查两种算法结果一致;它不是赋值号。
print(...)向终端输出数据,返回 None。显示中间结果、公式结果和比较结果。

效率不只看代码行数

当 n 很小时,两种方法都够快;n 很大时,循环要执行 n 次,公式依旧只做几步。算法分析关心输入规模变大时工作量如何变化,而不只是程序写了几行。

循环累加能帮助理解过程,公式法更快但需要证明正确。竞赛中既要能实现算法,也要理解为什么它得到正确答案。

尝试把循环次数也输出。再为 n=0、n=1、n=1000 测试,并解释每个结果。

代码如何运行

  1. 先按左侧题目给出的格式输入数据;程序通过 input() 读取,并在需要时转换数据类型。
  2. 程序自上而下执行语句;遇到条件、循环或函数调用时,按照右侧算法说明更新变量和处理数据。
  3. 最后由 print() 输出计算结果。可将左侧示例输入与输出逐项对照。

先自己跟踪一组小数据,记录循环前后变量的值;这比只看最终答案更容易理解程序。

自己动手试一试

测试 n=0、1 和较大的数;比较循环次数,并解释公式为什么不随 n 循环。

先在 lx25.py 中独立完成,再运行参考程序比较结果。修改程序时一次只改一个条件或步骤。