枚举法 - 像侦探一样逐个检查
中等0枚举法 —— 像侦探一样逐个检查,简单又可靠
小朋友们,你们玩过“猜数字”游戏吗?一个人心里想一个 1 到 10 的数字,另一个人猜,但只能通过问“是还是不是”来找答案。最笨但最可靠的方法就是从 1 问到 10,每个数字都试试——这其实就是 枚举法 的灵魂。
枚举法(也叫穷举法)就是 把所有可能的情况一个一个列出来,检查每个情况是不是满足要求。就像你丢了一枚硬币,你想在房间里找到它,你就从床头柜开始,一格一格地翻,直到找到为止。虽然有点慢,但一定不会漏掉。
在编程里,我们经常用循环语句(比如 for 或 while)来帮我们“挨个检查”。下面我们一步步拆解枚举法的用法,并看看它能在哪些地方帮我们解决问题。
一、枚举法是什么?—— 从“猜数字”到“找零钱”
枚举法听起来很高级,其实就是 把所有可能性列出来,一个一个试。比如:
- 你想知道班级里谁最高,就挨个同学量身高,比一比。
- 妈妈让你猜她买了几个苹果,你说“1个?2个?3个?……”直到猜对。
- 你有一把锁,忘了密码是 1234 还是 4321,那就两个都试一遍。
这些例子都用到枚举法。在编程中,我们用 循环 来替我们做“挨个检查”的苦力活,用 条件判断 来筛选出满足要求的结果。
二、枚举法的核心步骤:循环 + 条件判断
枚举法在代码中一般由两部分组成:
- 循环 —— 用来遍历所有可能的值(比如从 1 到 100)。
- 条件判断 —— 对每个值检查是否符合题目要求。
比如下面这段代码,找出 1 到 20 中所有的偶数:
# 枚举法:找出1到20中所有的偶数
print("1到20中的偶数有:")
for number in range(1, 21): # 从1到20逐个枚举
if number % 2 == 0: # 检查这个数是不是偶数
print(number, end=" ")
# 输出:2 4 6 8 10 12 14 16 18 20
你看,程序从 1 数到 20,每个数都问一遍“你除以 2 有没有余数?”如果没有余数,就说明它是偶数,我们就把它记下来。
三、生活中的枚举法例子
例子 1:统计班里身高超过 150 厘米的同学
假设我们有一个列表 heights 记录了全班 40 个同学的身高(单位:厘米)。我们要找出所有身高超过 150 厘米的同学。
# 枚举法:统计身高超过150厘米的同学
heights = [145, 152, 160, 138, 149, 155, 148, 162, 140, 158] # 假设只有10个同学
print("身高超过150厘米的同学:")
for h in heights: # 枚举每个同学的身高
if h > 150: # 检查是否超过150
print(h, end=" ") # 输出符合条件的值
# 输出:152 160 155 162 158
例子 2:找零钱组合
小明有 1 元、2 元、5 元的硬币各若干枚,他想凑出 10 元,可以怎么组合?枚举法可以列出所有可能的硬币数量搭配。
# 枚举法:找零钱组合凑出10元
print("能凑出10元的组合(1元、2元、5元):")
for one in range(0, 11): # 枚举1元硬币的数量(最多10个)
for two in range(0, 6): # 枚举2元硬币的数量(最多5个)
for five in range(0, 3): # 枚举5元硬币的数量(最多2个)
if 1*one + 2*two + 5*five == 10: # 检查总金额是否为10
print(f"1元×{one} + 2元×{two} + 5元×{five}")
这个例子用了三重循环,虽然看起来很慢,但对于这种小数据量完全没问题。
四、新手容易犯的错误
-
范围设置错误
比如要枚举 1 到 10,却写成range(1, 10),这样只会到 9。记得 Python 中range(start, stop)不包含stop本身。
✅ 正确:range(1, 11)或range(1, 21)(到 20)。 -
忘记初始化变量或输出语句放错位置
有时我们需要在循环外面定义一个变量(比如计数器),如果写在循环里面,每次循环都被重置。
❌ 错误:count = 0 for i in range(1, 11): if i % 2 == 0: count = count + 1 # 如果这句写在循环外,但变量定义放错了位置……正确写法:变量在循环前定义好。
-
枚举范围太大导致程序卡死
比如要枚举 1 到 1 亿,电脑会算很久,甚至内存溢出。所以枚举法适合数据量小的题目(通常不超过几百万次循环)。如果题目数据很大,需要想办法缩小范围。 -
条件判断写反
比如想找偶数却用了number % 2 != 0,结果找了一堆奇数。注意仔细审题。
五、完整示例:鸡兔同笼问题
鸡兔同笼,头共 35 个,脚共 94 只,问鸡和兔各有多少只?
枚举法:假设鸡有 chicken 只,兔有 rabbit 只,那么:
- 头数:
chicken + rabbit == 35 - 脚数:
2 * chicken + 4 * rabbit == 94
我们用循环枚举鸡的只数(0 到 35),然后算出兔的只数,再检查脚数是否匹配。
# 枚举法解决鸡兔同笼问题
head = 35 # 总头数
foot = 94 # 总脚数
found = False # 是否找到答案
for chicken in range(0, head + 1): # 枚举鸡的只数(0到35)
rabbit = head - chicken # 兔的只数 = 总头数 - 鸡的只数
if 2 * chicken + 4 * rabbit == foot: # 检查脚数是否匹配
print(f"鸡有 {chicken} 只,兔有 {rabbit} 只")
found = True
break # 找到一组解就退出循环(题目通常只有一组解)
if not found:
print("没有找到符合要求的解。")
输出:
鸡有 23 只,兔有 12 只
这段代码完整可运行。注意我们用了一个布尔变量 found 来记录是否找到解,找到了就 break 提前停止循环,避免浪费时间继续检查。
六、如何让枚举法更高效?—— 学会“聪明地枚举”
虽然枚举法很暴力,但我们可以让电脑少干点活:
- 缩小枚举范围:比如找两个数加起来等于 10,第一个数从 1 到 10 枚举就够了,第二个数可以直接用 10 减去第一个数,不用再枚举第二个数。
- 利用数学性质剪枝:比如判断质数,只要试到平方根就够了。
- 改循环为更快的算法:如果数据量太大,枚举会超时,需要换其他方法(比如二分查找、动态规划等)。
七、相关知识点指引
学会了枚举法,你还可以继续了解:
- 循环结构:
for和while的用法(尤其是range的多种写法) - 条件判断:
if-elif-else的嵌套 - 列表与字符串:枚举列表中的元素、字符串中的字符
- 算法复杂度:为什么枚举法有时很慢,以及如何估算循环次数
- 搜索剪枝:在枚举过程中提前排除不可能的情况(例如在“找零钱”例子中,如果当前硬币已经超过目标金额,提前停止内层循环)
枚举法就像你的侦探助手,虽然有时慢了一点,但从不撒谎。掌握它,你就能轻松解决许多编程入门题!
例题精讲
以下哪个问题最适合使用枚举法解决?
枚举法一定能保证找到最优解,但效率可能较低。
用枚举法求1到100中所有偶数的和,补全代码:
sum = 0
for i in range(1, 101):
if ___:
sum += i
print(sum)