递归三定律:
1、基本结束条件(最小规模问题的直接解决)
2、递归算法必须能改变状态向基本结束调节演进(减小问题规模)
3、调用自身(解决减小了规模的相同问题)
1 数列求和
def listsum(numlist):
if len(numlist) == 1:
return numlist[0]
else:
return numlist[0] + listsum(numlist[1:])
print(listsum([1,3,5,7,9]))
2 进制转换
def toStr(n, base):
convertString = '0123456789ABCDEF'
if n < base:
return convertString[n]
else:
return toStr(n//base, base) + convertString[n%base]
print(toStr(1453,16))
3 螺旋
import turtle
# forward、backward、left、right、
# penup、pendown、pensize、pencolor
t = turtle.Turtle()
def drawSpiral(t, linelen):
if linelen > 5:
t.forward(linelen)
t.right(90)
drawSpiral(t, linelen-5)
drawSpiral(t, 100)
turtle.done()
4 分形数
import turtle
def tree(len):
if len > 5:
t.forward(len)
t.right(20)
tree(len/2)
t.left(40)
tree(len/2)
t.right(20)
t.backward(len)
t = turtle.Turtle()
t.left(90)
t.pencolor('green')
tree(100)
t.hideturtle()
turtle.done()
5 谢尔宾斯基三角形
import turtle
def sierpinski(degree, points):
colormap = ['blue', 'red', 'green', 'white', '', 'orange']
drawTriangle(points,colormap[degree])
if degree > 0:
sierpinski(degree - 1,
{'left': points['left'],
'top': getMid(points['left'], points['top']),
'right': getMid(points['left'], points['right'])})
sierpinski(degree - 1,
{'left': getMid(points['left'],points['top']),
'top': points['top'],
'right': getMid(points['top'], points['right'])})
sierpinski(degree - 1,
{'left': getMid(points['left'],points['right']),
'top': getMid(points['top'], points['right']),
'right': points['right']})
def drawTriangle(points, color):
t.fillcolor(color)
t.penup()
t.goto(points['top'])
t.pendown()
t.begin_fill()
t.goto(points['left'])
t.goto(points['right'])
t.goto(points['top'])
t.end_fill()
def getMid(p1, p2):
return ((p1[0]+p2[0])/2, (p1[1]+p2[1])/2)
t = turtle.Turtle()
points = {'left': (-200, -100),
'top': (0, 200),
'right': (200, -100)}
sierpinski(5, points)
turtle.done()
6 汉诺塔
def moveTower(height, fromPole, withPole, toPole):
if height >= 1:
moveTower(height-1, fromPole, toPole, withPole) # 先把fromPole上的前n-1个盘挪到withPole
moveDisk(height, fromPole, toPole) # 再把最大的盘挪到toPole
moveTower(height-1, withPole, fromPole, toPole) # 然后把n-1个盘从withPole挪到toPole
def moveDisk(disk, fromPole, toPole):
print(f'moving disk[{disk}] from {fromPole} to {toPole}')
moveTower(3, '#1', '#2', '#3')
7 找零兑换
# 算最少兑币个数,可兑币种:1,5,10,25
# 递归算法
def minCoins1(num, coinValueList=[1,5,10,25]):
if num in coinValueList:
return 1
else:
minCoins = num
for x in [x for x in coinValueList if x < num]:
if 1 + minCoins1(num-x) < minCoins:
minCoins = 1 + minCoins1(num-x)
return minCoins
# 记忆化的递归算法
def minCoins2(num, coinValueList=[1,5,10,25]):
knownResult = {}
if num in coinValueList: # 递归结束条件
knownResult[num] = 1 # 记录最优解
return 1
elif num in knownResult:
return knownResult[num] # 查表成功,直接用最优解
else:
minCoins = num
for x in [x for x in coinValueList if x < num]:
numCoins = 1 + minCoins2(num-x)
if numCoins < minCoins:
minCoins = numCoins
knownResult[num] = minCoins
return minCoins
# 动态规划
def minCoins3(num, coinValueList=[1,5,10,25]):
minCoins = {}
for j in range(1, num+1):
if j in coinValueList:
minCoins[j] = 1
else:
minCoins[j] = j # 初始化j的最小兑币数
for i in [i for i in coinValueList if i < j]:
if 1 + minCoins[j-i] < minCoins[j]:
minCoins[j] = 1 + minCoins[j-i]
return minCoins[num]