循环嵌套经典算法
较难5循环嵌套,一个解决复杂问题的好帮手
你有没有遇到过这样的问题:需要反复做一件事,而这件事本身又需要重复好几次?比如:背一遍九九乘法表,里面每一行都要背1×1、1×2……这就是“重复中的重复”。在编程里,我们用循环嵌套来处理这种“大循环套小循环”的任务——外层循环控制大节奏,内层循环处理每个小细节。
下面我们就用两个经典案例来学习循环嵌套:打印九九乘法表,以及找出所有素数。这两个例子你肯定熟悉,但用代码写出来会特别有成就感!
1. 打印九九乘法表:先理解规律,再写出循环
九九乘法表有什么规律?
- 第1行有1个式子:1×1
- 第2行有2个式子:1×2、2×2
- 第3行有3个式子:1×3、2×3、3×3
- ……
- 第9行有9个式子:1×9、2×9…9×9
你会发现:行数 i 从1到9,每一行内的列数 j 从1到 i。这不就是典型的“外层循环控制行,内层循环控制列”吗?而且内层循环的终点取决于外层循环的当前值。
代码写出来是这样的(注意变量名用英文单词,每行加了中文注释):
for i in range(1, 10): # 外层循环,i 从1到9,代表行号(乘法表的第二个乘数)
for j in range(1, i + 1): # 内层循环,j 从1到i,代表第一个乘数
# 用f-string格式化输出,比如"1*2=2",并用制表符\t让每列对齐
print(f"{j}*{i}={i*j}", end="\t")
print() # 一行结束后换行
输出结果(部分省略中间行,最后两行):
1*1=1
1*2=2 2*2=4
1*3=3 2*3=6 3*3=9
... (4~7行略)
1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64
1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81
生活小例子:这就像你每天背单词——第一天背1个,第二天背2个,第三天背3个……外层循环是“天数”,内层循环是“当天要背的单词数量”。
2. 找出所有素数:用“试除法”加循环嵌套
什么是素数? 只能被1和它本身整除的数,比如2、3、5、7、11……1不是素数。
怎么判断一个数 n 是不是素数? 从2开始一直试到 n-1,看看有没有数能整除 n。如果有一个能整除,n 就不是素数;如果没有,n 就是素数。
如果我们要找100以内的所有素数,就需要对每个数(从2到100)做一次判断。每个判断又需要一个小循环(从2试到 n-1)。这就是“外层循环遍历候选数,内层循环做试除”。
代码实现(注意:内层循环每次都要重新假设这个数是素数):
for n in range(2, 101): # 外层:检查2到100的每个数
is_prime = True # 先假设当前数n是素数(“嫌疑人”是无辜的)
for i in range(2, n): # 内层:用2到n-1去试除
if n % i == 0: # 如果能被i整除,说明不是素数
is_prime = False # 推翻假设
break # 不用再试后面更大的i了,直接退出内层循环
if is_prime: # 如果内层循环结束后,is_prime仍然是True
print(n, end=" ") # 打印这个素数
输出(一行显示所有100以内的素数):
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
生活小例子:你想从全班40位同学中找出所有“从未迟到的同学”。外层循环是逐个同学检查,内层循环是检查这个同学的每一天(假设有100天)是否迟到。一旦发现某一天迟到,就马上标记“不是从未迟到”,然后不用再看后面的日子了(break)。全部日子检查完还没发现迟到,就说明他是“从未迟到”的同学。
3. 循环嵌套的常见错误(新手最容易踩的坑)
错误1:内层循环的变量名和外层循环的变量名搞混
比如打印九九乘法表时,把内层循环写成 for j in range(1, i+1),却用了 j 的地方写成了 i。结果会输出一堆重复的数字。
解决方法:在外层用 i 或 row,内层用 j 或 col,不要混用。
错误2:忘记重置“标志变量”
找素数时,is_prime = True 必须放在外层循环里面(每检查一个新数之前都要重新假设为真)。如果放在外层循环外面,判断完第一个数后 is_prime 变成了 False,后面所有数都不会被打印。
正确做法:把 is_prime = True 放在 for n in ... 的下一行。
错误3:内层循环的终点范围搞错
比如找素数时,内层循环写成 for i in range(2, n+1),这样包括 n本身,会导致 n%n==0,从而把素数也当成合数。
正确范围:应该是 range(2, n),即从2到n-1。
错误4:忘记使用 break 提前退出内层循环
虽然不写 break 程序也能正常运行,但会做很多无用功。比如检查100是不是素数,试到2发现能整除,其实已经可以下结论了,但如果不 break 还会继续试3、4……浪费时间。养成“找到证据就立刻停止”的好习惯。
4. 完整可运行的示例:找出100以内的素数并统计个数
下面是一个完整的程序,它不仅输出所有素数,还统计数量。你可以直接复制到 Python 中运行。
# 找出100以内的所有素数,并统计个数
count = 0 # 计数器,初始为0
for n in range(2, 101): # 外层循环:从2到100
is_prime = True # 先假设当前数字是素数
for i in range(2, n): # 内层循环:用2到n-1试除
if n % i == 0: # 如果能整除
is_prime = False # 不是素数
break # 立即退出内层循环
if is_prime: # 如果仍是素数
print(n, end=" ") # 打印这个素数,用空格分隔
count = count + 1 # 计数器加1
print() # 换行
print("100以内的素数共有", count, "个")
输出结果(最后一行):
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
100以内的素数共有 25 个
小提示:如果把
range(2, 101)改成range(2, 1001),就能找出1000以内的所有素数。试一试吧!
5. 生活中的其他循环嵌套例子
例1:考试分数统计
老师要统计3个班级,每个班有40名同学的数学成绩。外层循环遍历班级,内层循环遍历班里的每个同学。
例2:课表安排
一周有5天,每天有8节课。外层循环是星期几,内层循环是第几节课。
例3:零食分发
妈妈买了3种零食,每种零食要分给2个孩子。外层循环是零食种类,内层循环是孩子编号。
这些都可以用循环嵌套来实现。你只要想清楚“哪个是外层的大循环,哪个是内层的小循环”。
6. 下一步可以学什么?
学会循环嵌套后,你就能挑战更多算法了,比如:
- 冒泡排序:用两个循环给数字排队(外层控制轮数,内层控制比较次数)。
- 百钱百鸡:中国古代的数学问题,用循环嵌套找所有可能解。
- 图案打印:打印菱形、空心三角形等(用循环嵌套控制空格和星号)。
此外,你还会经常用到 break 和 continue 来优化循环,以及 else 子句(循环正常结束才执行 else)。这些内容会让你的代码更高效、更聪明。
记住:循环嵌套的核心就是“先画大圈,再在小圈里做细活”。多敲几遍代码,让手指记住这种感觉,以后你也能自己设计算法解决新问题!
例题精讲
以下代码执行后,共输出多少行内容? for i in range(1, 4): for j in range(1, i + 2): print(i, j)
在嵌套循环中,break语句的作用是立即终止所有外层循环,使程序完全跳出整个循环结构。
以下代码用于判断一个大于1的整数n是否为素数。请补全条件。
def is_prime(n):
for i in range(2, n):
if ___ :
return False
return True下列代码运行后,打印的图形形状是? for i in range(1, 6): for j in range(1, 6 - i + 1): print('*', end='') print()
使用嵌套循环输出九九乘法表时,内层循环变量j的上限通常设置为外层循环变量i的值,即内层循环次数随外层增加而增加。