迭代
1.1 定义
- 迭代算法是用计算机解决问题的一种基本方法。
- 它利用计算机运算速度快、适合做重复性操作的特点,让计算机对一组指令(或一定步骤)进行重复执行,
- 在每次执行这组指令(或这些步骤)时,都从变量的原值推出它的一个新值。
1.2 处理迭代问题的条件()
- 确定迭代变量(三个变量,a1,a2,a3)---------------------------具有的原始变量(a1=1,a2=1),用原始变量可以推出新值(a3=2),通过重复操作把原始变量重新赋值(a1=a2,a2=a3),持续推出新值a3
- 建立迭代关系式------------------------关键用上一个变量推断出下一个变量的公式(a3=a2+a1),通常使用递推或倒推来完成
- 对迭代过程进行控制。
3.1 知道迭代次数:求出迭代次数,利用循环控制
3.2 不知道迭代次数:需要进一步分析出用来结束迭代过程的条件
1.3 斐波那契迭代图解
1.4 具体案例分析
1.4.1 一个豢养场引进一只刚出生的新品种兔子,这种兔子从出生的下一个月开始,每月重生一只兔子,重生的兔子也如此繁殖。如果所有的兔子都不死去,问到第 12 个月时,该豢养场共有兔子多少只?
解题分析:
条件①
:从这种兔子从出生的下一个月开始,每月重生一只兔子得知,(n+1)月兔子数量=n月兔子数量 × 2
假设: 1 月 有 m 1 只 , 2 月 有 m 2 只 , 3 月 有 m 3 只 , 4 月 有 m 4 只 , … … , n 月 有 m n 只 1月有m_1只,2月有m_2只,3月有m_3只,4月有m_4只,……,n月有m_n只 1月有m1只,2月有m2只,3月有m3只,4月有m4只,……,n月有mn只
条件②
: m 2 = m 1 + m 1 ∗ 1 , m 3 = m 2 + m 2 ∗ 1 , … … m n = m n − 1 + m n − 1 ∗ 1 m_2=m_1+m_1*1,m_3=m_2+m_2*1,……m_n=m_{n-1}+m_{n-1}*1 m2=m1+m1∗1,m3=m2+m2∗1,……mn=mn−1+mn−1∗1
根据条件①②
得到:公式①
m n = 2 m n − 1 m_n=2m_{n-1} mn=2mn−1
根据公式①
里的变量对应设置迭代变量:
x,y
根据公式①和迭代变量
确定迭代关系:
y = 2 x ( x > = 2 ) ; x = y ; y=2x(x>=2);x=y; y=2x(x>=2);x=y;
根据问到第 12 个月时得到迭代控制条件
:[1,12) 循环11次
迭代变量:x=1,y 迭代关系式 y=2x(x>=2);x=y; 迭代次数:[1,12] 循环11次
# 代码实现
def ra():
x = 1 # 第1个月
for echo in range(1,12): # 后边11个月
y = 2 * x
x = y
print('12个月兔子繁殖总数是%d' % y)
# 调用函数
ra()
输出: 12个月兔子繁殖总数是2048
1.4.2 阿米巴用简单分裂的方式繁殖,它每分裂一次要用 3 分钟。将若干个阿米巴放在一个盛满营养液的容器内, 45 分钟后容器内充满了阿米巴。已知容器最多能够装 2 20 2^{20} 220 阿米巴个。试问,开始的时候往容器内放了多少个阿米巴?
解题分析:
条件①
:从阿米巴用简单分裂的方式繁殖得知,(n-1)月阿米巴数量=n月阿米巴数量 / 2
假设: 1 月 有 m 1 只 , 2 月 有 m 2 只 , 3 月 有 m 3 只 , 4 月 有 m 4 只 , … … , n 月 有 m n 只 1月有m_1只,2月有m_2只,3月有m_3只,4月有m_4只,……,n月有m_n只 1月有m1只,2月有m2只,3月有m3只,4月有m4只,……,n月有mn只
条件②
: m 1 = m 2 / 2 , m 2 = m 3 / 2 , … … m n − 1 = m n / 2 m_1=m_2/2,m_2=m_3/2,……m_{n-1}=m_n/2 m1=m2/2,m2=m3/2,……mn−1=mn/2
根据条件①②
得到:公式①
m n − 1 = m n / 2 m_{n-1}=m_{n}/2 mn−1=mn/2
根据公式①
里的变量对应设置迭代变量:
y= m n m_{n} mn,x = m n − 1 m_{n-1} mn−1
根据公式①和迭代变量
确定迭代关系:
x = y / 2 ; y = x ; x=y/2;y=x; x=y/2;y=x;
根据45 分钟后容器内充满了阿米巴,它每分裂一次要用 3 分钟得到45/3=15迭代控制条件
:[1,16) 循环15次
迭代变量:x,y=2^20 迭代关系式 x=y/2;y=x; 迭代次数:[1,16] 循环15次
# 代码实现
def ra():
y=2**20
for echo in range(1,16):
x = y / 2
y = x
print(x,y)
# 调用函数
ra()
输出: 初始阿米巴数量为32
1.4.3 验证谷角猜想。日本数学家谷角静夫在研究天然数时发觉了一个奇怪现象:对于任意一个天然数 n ,若 n 为偶数,则将其除以 2 ;若 n 为奇数,则将其乘以 3 ,然后再加 1 。如此经过有限次运算后,分能够得到天然数 1 。人们把谷角静夫的这一发觉叫做“谷角猜想”。
# 构造函数
def ra(y):
while(y!=1):
n = 0 #计数器
if y % 2 == 0:
y = y / 2
n=n+1
else :
y = y * 3 + 1
n=n+1
print('得到自然数%d,总循环次数%d' % (y,n))
# 调用函数
ra(34)
# 输出:得到自然数1,总循环次数1
递归
1.1 定义
递归是设想和描述算法的一种有力的工具,由于它在复杂算法的描述中被经常采用,为此在进一步引见其他算法设想方法之前先讨论它。
1.2 使用递归描述算法的特征
- 为求解规模为N的问题,设法将它分解成规模较小的问题,然后从这些小问题的解方便地构造出大问题的解
- 并且这些规模较小的问题也能采用同样的分解和分析方法,分解成规模更小的问题,并从这些更小问题的解构造出规模较大问题的解
- 特别地,当规模N=1时,能间接得解
1.3 斐波那契数列递归图解
1.4 斐波那契(Fibonacci)数列(黄金分割比例(0.618))
斐波那契数列为:0、1、1、2、3、5……,
后一项等于前两项之和,即: a n = a n − 1 + a n − 2 a_n=a_{n-1}+a_{n-2} an=an−1+an−2
1.5 斐波那契数列-生兔子
经过月数 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
兔子对数 | 1 | 1 | 2 | 3 | 5 | 8 | 13 | 21 | 34 | 55 | 89 | 144 |
① 迭代实现算到100000个月未卡死
- 迭代式: n 3 = n 1 + n 2 ; n 1 = n 2 ; n 2 = n 3 n_3=n_1+n_2;n_1=n_2;n_2=n_3 n3=n1+n2;n1=n2;n2=n3
- 迭代变量(运算开始): a 1 = 1 , a 2 = 1 a_1=1,a_2=1 a1=1,a2=1
- 控制条件:while(用户输入)
# 定义函数
def fib():
n1=1
n2=1
n3=0
n = int(input('请输入查询几个月的兔子总数'))
if n < 1 :
print('输入数据有误')
if n ==1 or n ==2 :
return 1
if(n > 2):
m=n
while(m>2):
n3=n1+n2
n1 = n2
n2 = n3
m-=1
print('%d个月的兔子总数为%d' % (n,n3))
# 调用函数
fib()
请输入查询几个月的兔子总数 12
# 输出 :12个月的兔子总数为144
② 递归实现算到40个月卡死
- 运算开始:fib(1)=1,fib(2)=1
# 定义函数
def fib(n):
if n < 1:
return '输入数据有误'
if n == 1 or n == 2: # fib(1)=1,fib(2)=1 运算起点
return 1
if n > 2:
return fib(n-1)+fib(n-2)
# 调用函数
fib(12)
# 输出:144
1.6 汉诺塔
计算汉诺塔几层需要多少步: 2 层 数 − 1 2^{层数}-1 2层数−1
1.6.1 核心思想:
- 条件:三个轴(x,y,z)n个木盘
- 解决:①把(n-1)个木盘从x轴转移到y轴,②把x轴的第n个木盘转移到z轴,③把y轴的(n-1)个木盘转移到z轴
1.6.2 图解
- 分析①:把
x
轴的木盘移动到z
轴,需要y
轴当中介
- 分析②:把
y
轴的木盘转移到z
轴,需要x
轴当中介
- 递归思想,
(n-1)层转移的时候思路还是一样的,一直向下递归,直到n=1时,执行相应的操作,并依次把结果向上递归回去。
1.6.3 代码实现
# 汉诺塔游戏攻略
m = 0 # 计数器,记录共用了多少步
def han(n,x,y,z): # n 盘子数,x,y,z 对应三根针
if( n == 1 ):
global m
m=m+1
print(x,'----->',z,'------>',m)
else:
han(n-1,x,z,y) # 将前n-1个盘子从x移动到y上,z为中转
m=m+1
print(x,'----->',z,'------>',m) # 最后一个盘子移动到z上
han(n-1,y,x,z) # 将y上的n-1个盘子移动到z上
n = int(input('汉诺塔层数'))
han(n,'X','Y','Z')