【程式設計5】斐波那契數列 + 遞迴+LeetCode50
傳送門:https://leetcode-cn.com/problems/powx-n/
一、LeetCode 50. Pow(x, n)
1、題目描述
實現 pow(x, n) ,即計算 x 的 n 次冪函式。
2、示例
示例 1:
輸入: 2.00000, 10
輸出: 1024.00000
示例 2:
輸入: 2.10000, 3
輸出: 9.26100
示例 3:
輸入: 2.00000, -2
輸出: 0.25000
解釋: 2-2 = 1/2^2 = 1/4 = 0.25
3、說明
-100.0 < x < 100.0
n 是 32 位有符號整數,其數值範圍是 [−231, 231 − 1] 。
4、分析
本題重點在於邊界條件的分析和處理
- 如果 n < 0,是不是 n = -n, x = 1 / x ,再進行遞迴就能解決了呢?
- 如果 n = Intege.MIN_VALUE,n = -n 會出現溢位,怎麼辦呢?
- 我們可以先將 n / 2 賦值給 a,再將 a = -n,就不會出現溢位問題。
5、實現
class Solution {
public:
double myPow(double x, int n) {
if(n == 0)
return 1;
int a = n/2;
if (n < 0)
{
a = -a;
x = 1.0/x;
}
double res = myPow(x, a);
if(n % 2 == 0)
return res * res;
else
return res * res * x;
}
};
二、遞迴
1、定義
- 若一個物件部分的包含自己或用它自己給自己定義,則這個物件是遞迴的;
- 若一個過程直接或間接的呼叫自己,則這個過程是遞迴的。
2、思想
把問題分解為規模更小具有與原問題相同解法的子問題
==》優點:思考的方式更加簡單,程式也更加簡練。
==》缺點:增加了壓棧開銷,因此空間複雜度比較高。
3、遞迴條件
- 減小問題規模,並使子問題與原問題有相同解法。
- 設定出口,如果沒有出口那麼程式會一直遞迴下去。
三、斐波那契數列
斐波那契數列是一個非常典型的遞迴問題。
1、迴圈方法
long Fibonacci1(size_t N)
{
long first = 1;
long second = 1;
long sum = 0;
if(N < 3)
return 1;
else
{
for(size_t i = 3; i <= N; i++)
{
sum = first + second;
first = second;
second = sum;
}
return sum;
}
}
==》時間複雜度:O(n)
==》空間複雜度:O(1)
2、遞迴方法1
long Fibonacci2(size_t N)
{
if(N < 3)
return 1;
else
return Fibonacci2(N-1) + Fibonacci2(N-2);
}
==》由後向前計算
==》時間複雜度:O(n2)
==》空間複雜度:O(n)
3、遞迴方法2
long Fibonacci3(long first, long second, size_t N)
{
if(N < 3)
return second;
else
return Fibonacci3(second, first + second, N - 1);
}
==》前向後計算——尾遞迴方法
==》在進行遞迴時函式只會使用第一次壓棧所開闢的棧空間,在一個棧空間內迴圈,而不會開闢別的棧空間,所以這種方式時間複雜度為O(N),空間複雜度為O(1),是一種非常高效的遞迴方式。
4、遞迴方法3
long *Fibonacci4(size_t N)
{
long *array = new long[N+1];
if(N == 0)
return NULL;
array[0] = 1;
array[1] = 1;
for(size_t i = 2; i <= N; i++)
{
array[i] = array[i-1] + array[i-2];
}
return array;
}
四、遞迴函式的複雜度
在演算法的分析中,當一個演算法中包含遞迴呼叫時,其時間複雜度的分析==》一個遞迴方程的求解。
而對遞迴方程的求解,目前主流的方法:代入法,迭代法,公式法,母函式法,差分方程法。
1、代入法
- 首先要對這個問題的時間複雜度做出預測;
- 然後將預測帶入原來的遞迴方程,如果沒有出現矛盾,則是可能的解;
- 最後用數學歸納法證明。
示例
遞迴問題:T(n)=4T(n/2)+O(n)
(1)預測時間複雜度:O(n2)
(2)設T(n)=kn2(其中k為常數),將該結果帶入方程
(3)可得:左=kn2,右=4k(n/2)2+O(n)=kn2+O(n)
(4)由於n2 的階高於 n 的階,因而左右兩邊是相等的;
(5)數學歸納法進行驗證即可
2、迭代法
- 迭代的展開方程的右邊,直到沒有可以迭代的項為止;
- 這時通過對右邊的和進行估算來估計方程的解。
- 比較適用於分治問題的求解。
遞迴方程的一般形式
示例
(1)遞迴方程如下:
(2)迭代過程如下:
容易知道,直到
時,遞迴過程結束,這時我們計算如下:
==》該演算法的時間複雜度:O(n2)
3、公式法
針對形如:T(n) = aT(n/b) + f(n)的遞迴方程
==》分治法的時間複雜度,即一個規模為n的問題被分成規模均為n/b的a個子問題,遞迴地求解這a個子問題,然後通過對這a個子問題的解的綜合,得到原問題的解。
==》公式法對於分治問題最好的解法