1、斐波那契數列
斐波那契數列(Fibonacci sequence),又稱黃金分割數列、因數學家列昂納多·斐波那契(Leonardoda Fibonacci)以兔子繁殖為例子而引入,故又稱為“兔子數列”,指的是這樣一個數列:1、1、2、3、5、8、13、21、34、……在數學上,斐波納契數列以如下被以遞推的方法定義:F(1)=1,F(2)=1, F(3)=2,F(n)=F(n-1)+F(n-2)(n>=4,n∈N*)在現代物理、準晶體結構、化學等領域,斐波納契數列都有直接的應用,為此,美國數學會從1963年起出版了以《斐波納契數列季刊》為名的一份數學雜誌,用於專門刊載這方面的研究成果。
(1)、遞迴演算法 (三點: 終止條件(邊界),最優子結構 F(1)=1,F(2)=1, F(3)=2,F(n)=F(n-1)+F(n-2) 狀態轉移公式 F(n)=F(n-1)+F(n-2))
def fab(n): # 終止條件 邊界 if n <= 2: return 1 else: # 最優子結構 狀態轉移公式 return fab(n - 1) + fab(n - 2)
(2)、優化 遞迴演算法 會重複計算多次同一個式子 如圖 相同的顏色代表了方法被傳入相同的引數。所以需要記錄下已經計算過得數,防止重複計算
# 記錄已經計算過得 值 dict_fab = {} def fab_2(n): # 終止條件 邊界 if n <= 2: return 1 elif dict_fab.get(n): print('*') return dict_fab.get(n) else: # 最優子結構 狀態轉移公式 dict_fab[n] = fab_2(n - 1) + fab_2(n - 2) return dict_fab[n]
(3)、動態規劃
# 最終優化 動態規劃 (大問題化成若干相同型別的子問題 然後一個個解決子問題) def fab_3(n): # 由前往後推 a = 1 b = 1 if n <= 2: print('fab({})={}'.format(n, b)) return 1 for i in range(n - 2): print(a, b) a, b = b, a + b print('fab({})={}'.format(n, b)) return b
2、盛水問題 Python解法(題目連結 https://leetcode.com/problems/trapping-rain-water/description/ )
(1)、暴力解法
def trap(height): sum_water = 0 size = len(height) for i in range(size): max_left = 0 max_right = 0 for j in range(0, i + 1): max_left = max(max_left, height[j]) for j in range(i, size): max_right = max(max_right, height[j]) sum_water += min(max_left, max_right) - height[i] return sum_water
(2)、動態規劃(記憶演算法,記錄i 位置的左右 最大數,減少for迴圈層級 時間複雜度 有o(n²)變為 o(n))
def trap_water_dy(): height = [0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1] sum_water = 0 size = len(height) max_left_lsit = [None]*size max_left_lsit[0] = height[0] max_right_list = [None]*size max_right_list[-1] = height[-1] for i in range(1, size): max_left_lsit[i] = max(height[i], max_left_lsit[i - 1]) for i in range(size-1): max_right_list[size - 2 - i] = max(height[size - 2 - i], max_right_list[size - i - 1]) for i in range(size): sum_water += min(max_left_lsit[i], max_right_list[i]) - height[i] return sum_water
(3)、雙指標
def trap_two_point(): height = [0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1] left = 0 right = len(height) - 1 ans = 0 left_max = 0 right_max = 0 while left < right: # 迴圈陣列一遍 if height[left] < height[right]: # 當左邊的小於右邊的 能裝多少水 由左邊的最高高度決定 if height[left] >= left_max: left_max = height[left] ans += (left_max - height[left]) left += 1 else: # 當右邊小於左邊時 裝的水量由右邊的最高高度決定 if height[right] >= right_max: right_max = height[right] ans += (right_max - height[right]) right -= 1 return ans