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,只要某一方先使自己在橫向、豎向或斜項有三個連續的標記,則判該方獲勝。
假設此時,已到如下局勢: