遞歸算法【原理及經典應用舉例】

遞歸算法【原理及經典應用舉例】

遞歸算法

遞歸,就是在運行的過程中調用自己。

構成遞歸需具備的條件:

  1. 子問題須與原始問題爲同樣的事,且更爲簡單;
  2. 不能無限制地調用本身,須有個出口,化簡爲非遞歸狀況處理。

在數學和計算機科學中,遞歸指由一種(或多種)簡單的基本情況定義的一類對象或方法,並規定其他所有情況都能被還原爲其基本情況。

遞歸應用

遞歸算法一般用於解決三類問題:

(1)數據的定義是按遞歸定義的。(例如:Fibonacci函數)

(2)問題解法按遞歸算法實現。
這類問題雖則本身沒有明顯的遞歸結構,但用遞歸求解比迭代求解更簡單,如Hanoi問題。

(3)數據的結構形式是按遞歸定義的。
如二叉樹、廣義表等,由於結構本身固有的遞歸特性,則它們的操作可遞歸地描述。

設計遞歸算法的步驟:

1.確定遞歸公式

2.確定邊界(終了)條件

遞歸的缺點

遞歸算法解題相對常用的算法如普通循環等,運行效率較低。因此,應該儘量避免使用遞歸,除非沒有更好的算法或者某種特定情況,遞歸更爲適合的時候。在遞歸調用的過程當中系統爲每一層的返回點、局部量等開闢了棧來存儲。遞歸次數過多容易造成棧溢出等。

簡單遞歸問題舉例

  1. 斐波納契數列(Fibonacci Sequence),又稱黃金分割數列。
    1、1、2、3、5、8、13、21…

Fib(0) = 1,Fib(1) = 1。
對所有n > 1的整數:
Fib(n) = (Fib(n-1) + Fib(n-2))

【斐波那契】

n = int(input())
def Fib(n):
	if n == 0 or n == 1:
		return 1
	else:
		return Fib(n-1)+Fib(n-2)
# 輸出
for i in range (n):
	print (Fib(i),end=' ')
  1. 階乘

1!= 1
對所有n > 1的整數:
n! = (n * (n-1)!)

【階乘】

n = int(input())
def Fact(n):
	if n == 1:
		return 1
	else:
		return n*Fact(n-1)
# 輸出
print (Fact(n))
  1. 漢諾塔問題

已知有三根針分別用A, B, C表示,在A中從上到下依次放n個從小到大的盤子。

現要求把所有的盤子從A針全部移到C針,移動規則是:可以使用B臨時存放盤子,每次只能移動一塊盤子,而且每根針上不能出現大盤壓小盤,找出移動次數最小的方案。

A,B,C三個盤子,分別爲初始位,過渡位,目標位:

(1)將最上面的n-1個圓盤從初始位移動到過渡位

(2)將初始位的最底下的一個圓盤移動到目標位

(3)將過渡位的n-1個圓盤移動到目標位

【漢諾塔問題】

count = 0
def hanoi(n,start,end,mid):
    global count
    if n == 1:
        print("{}:{}->{}".format(n,start,end))
        count += 1
    else:
        hanoi(n-1,start,mid,end)
        print("{}:{}->{}".format(n,start,end))
        count += 1
        hanoi(n-1,mid,end,start)
hanoi(3,"A","C","B")
print(count)

【輸出結果】

1:A->C
2:A->B
1:C->B
3:A->C
1:B->A
2:B->C
1:A->C
7

  1. 上臺階有多少種走法:

樓梯有n階臺階,上樓可以一步上1階,也可以一步上2階,計算共有多少種不同的走法.

設n階臺階的走法數爲f(n)

n=1 時:有1種走法
n=2 時:有2種走法
n>2時: f(n-1)+f(n-2)

【上臺階問題】

def Up(n):
    if n == 1:
        return 1
    elif n == 2:
        return 2
    else:
        return Up(n-1)+Up(n-2)
print(Up(4))
  1. 遞歸法求數組最大值:

數組爲空:返回0
數組長度爲1:返回這個值
數組長度大於1:比較第一個值和剩餘元素的最大值(調用)

【數組最大值】

def max_num(lists):
    if lists == []:
        return 0
    elif len(lists) == 1:
        return lists[0]
    else:
        if lists[0] > max_num(lists[1:]):
            return lists[0]
        else:
            return max_num(lists[1:])
print(max_num([1, 3, 4, 2]))
  1. 求累加值:1+2+3+…+n

【累加值】

def add(n):
    if n == 1:
        return n
    else:
        return n+add(n-1)
print (add(3))
  1. 楊輝三角

遞歸求楊輝三角第i行,第j列的值

【楊輝三角求值及輸出】

# 楊輝三角
def yang(i,j):
    if i==j or j==1:
        return 1
    return yang(i-1,j-1)+yang(i-1,j)
# 輸出一個n行的楊輝三角
def Outyang(n):
    for i in range(1,n+1):
        for j in range(1,i+1):
            print (yang(i,j),end=' ')
        print('')
Outyang(5)

【輸出】

1
1 1
1 2 1
1 3 3 1
1 4 6 4 1

  1. 迴文串

長度爲1:返回True
長度大於1:
判斷:最外層兩個是否相同
不同:返回False
相同:內移一層(調用)

【判斷是否爲迴文串】

def isHuiWen(str):
    if(len(str) <2):
        return True
    elif str[0] != str[-1]:
        return False
    else:
        return isHuiWen(str[1:-1])
str = input("請輸入一個字符串:")
if isHuiWen(str):
    print("該字符串爲迴文字符串")
else:
    print("該字符串不是迴文")
  1. 字符串的全排列
    原文鏈接:https://blog.csdn.net/qq_42015869/article/details/79996227

全排列:

1、列表只有一個元素[a],它的全排列只有a。

2、列表有兩個元素[a, b],它的全排列爲[a, b], [b, a]:
{ 將第一個元素a固定,對b進行全排列得到[a, b]。
將第一個元素與第二個元素交換得到[b, a]。
將b固定,對a進行全排列,得到[b, a] }

3、列表有三個元素[a, b, c]
{ 將a固定,對bc進行全排列{ 將b固定,對c全排列[abc]。交換bc,將c固定對b進行全排列[acb] }
交換ab,[b, a, c] 對ac進行全排列{ … }
… …}

4、列表有n個元素,將第一個元素固定,對剩下n - 1個元素進行全排列。
將第一個元素依此與其他元素交換,對每次交換後剩下的n-1個元素進行全排列。

5、對剩下的n - 1個元素全排列,同上,固定後對n - 2排列。

6、直到數組數量爲1,全排列就是它自己,完成一次排列。

【字符全排列】

def perm(data, begin, end):
    if begin == end:  # 遞歸結束條件,當交換到最後一個元素的時候不需要交換,1的全排列還是1print(data)  # 打印一次排列完成後的數組。
    else:
        j = begin
        for i in range(begin, end):  # 從begin到end全排列。
            data[i], data[j] = data[j], data[i]
            perm(data, begin + 1, end)
            data[i], data[j] = data[j], data[i]  # 遞歸完成後,交換回原來的位置。
arr = [1, 2, 3, 4, 5]
perm(arr, 0, len(arr))
  1. 二分法查找
def searchNum(ls, num, lower=0, upper=None):
   if upper is None:
       upper = len(ls) - 1
   mid = (lower + upper) // 2
   if mid == 0 and num != ls[0]:
       return "不存在"
   if mid == len(ls) - 1 and num != ls[-1]:
       return "不存在"

   if num == ls[mid]:
       return mid, ls[mid]
   elif num < ls[mid]:
       return searchNum(ls, num, lower, mid)
   else:
       return searchNum(ls, num, mid + 1, upper)

L = [5, 8, 9, 12, 17, 19, 20, 22]
n = 8
result = searchNum(L, n)
print(result)

發佈了54 篇原創文章 · 獲贊 5 · 訪問量 4846
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章