10.4 递归的应用
10.4.1 递归二分法搜索
二分法搜索,可以采用递归的形式,其时间复杂度仍是O(log n)。但不同的是,每一次函数调用的时间复杂度是O(1),只是整个算法的最坏情况总共调用了log n次,因此时间复杂度仍是O(log n)。
#-*-coding: utf-8-*-
# 二分法搜索的递归形式
def recBinarySearch(target, theSeq, first, last):
if first > last:
return False
else:
mid = (first + last) / 2
if theSeq[mid] == target:
return True
elif target < theSeq[mid]:
return recBinarySearch(target, theSeq, first, mid-1)
else:
return recBinarySearch(target, theSeq, mid+1, last)
10.4.2 Hanoi塔问题
这个问题起源于一个类似传说故事,在Hanoi这个地方有一个寺庙,这里有3根柱子和64个大小不同的金碟子。每个碟子有一个孔可以穿过。所有的碟子都放在第一个柱子上,而且按照从上到下碟子的大小依次增大的顺序摆设。如下图:
现在,假定寺庙里的僧侣要移动这些碟子,将它们从最左边移动到最右边的柱子上。不过移动的规则如下:
1. 每次只能从一个柱子的最上面移动一个碟子到另外一个柱子上。
2. 不能将大碟子放到小碟子的上面。
考虑n个碟子的问题,先将最上面的n-1个碟子移动到中间的柱子上,再将最下面的碟子移动到最右边的柱子上,再将n-1个碟子移动到最右边的柱子上。其终止条件显然是当只有一个碟子时,只需将其直接移动至最右边的柱子即可。
#-*-coding: utf-8-*-
# hanoi塔问题
def move(n, src, dest, temp):
if n >= 1:
move(n-1, src, temp, dest)
print "Moved %d -> %d" % (src, dest)
move(n-1, temp, dest, src)
其时间复杂度的是O(2ⁿ),其递归调用树如下所示,递归调用次数是2ⁿ - 1。
按照定义,x的n次方,是x自乘n次。即如下代码所示:
#-*-coding: utf-8-*-
# 指数运算
def exp1(x, n):
y = 1
for i in range(n):
y *= x
return
但也可以每两个x相乘,作为一个新的x,再重复之前的过程。需要注意的是n是奇数时,需要单独将一个x提取出来。
def exp2(x, n):
if n == 0:
return 1
result = exp(x * x, n/2)
if n % 2 == 0:
return result
else:
return x * result
10.4.4 井字棋游戏
井字棋游戏,是在九宫格上,一方标记o,另一方标记x,只要某一方先使自己在横向、竖向或斜项有三个连续的标记,则判该方获胜。
假设此时,已到如下局势: