鏈接:楊輝三角
描述:
給定一個非負整數 numRows,生成楊輝三角的前 numRows 行。比如給定5,則生成以下數組。
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
思路:
既然是講遞歸,那麼就先尋找規律。根據楊輝三角的定義,很容易的知道第n行和第n+1行元素之間的關係——假設低n行的數據爲f(n),f(n,x)爲第n行的x個元素,則f(n+1,x) = f(n,x-1) + f(n,x)。可以很容易的想到通過遞歸得到任意行的數據,之後只要遍歷n遍即可得到想要的楊輝三角了。代碼如下:
class Solution {
public:
// 生成楊輝三角
vector<vector<int>> generate(int numRows) {
vector<vector<int>> ret;
for (size_t i = 0; i < numRows; i++)
{
ret.push_back(getLine(i+1));
}
return ret;
}
// 得到楊輝三角中指定行的數據
vector<int> getLine(int row)
{
vector<int> ret;
for (size_t i = 0; i < row; i++)
{
if (i == 0 || i == row - 1)
{
ret.push_back(1);
continue;
}
vector<int> vLast = getLine(row - 1);
int nValue = vLast[i - 1] + vLast[i];
ret.push_back(nValue);
}
return ret;
}
};
問題:
雖然很容易的解決了問題,但是這裏存在一個弊端,就是運行超時。因爲當爲了獲取f(n+1)的數據時,它會先獲取f(n),但是f(n)又依賴於f(n-1),這樣當爲了 得到f(5)的數據,f(4)被調用2次,f(3)被調用4次,f(2)被調用8次,造成時間和空間上成指數的開銷。爲了解決這個問題,非遞歸實現是一個更好的選擇。
非遞歸實現
vector<vector<int>> generate(int numRows) {
vector<vector<int>> ret;
for (size_t i = 0; i < numRows; i++)
{
vector<int> row;
for (size_t k = 0; k < i + 1; k++)
{
if (k == 0 || k == i)
{
row.push_back(1);
continue;
}
row.push_back(ret[i - 1][k - 1] + ret[i - 1][k]);
}
ret.push_back(row);
}
return ret;
}
這個解法大比遞歸不管是時間還是空間複雜度都降低了很多,但其實還可以做進一步的優化。仔細觀察,楊輝三角的每一行都是對稱的,此時只需要獲取f(n)中的0~n/2+1的數據,然後將他們複製到後面即可。優化的代碼這裏就不再給出了(因爲我懶_)