[leetcode刷題筆記] 楊輝三角 I&II

題目地址

  1. https://leetcode-cn.com/problems/pascals-triangle/ 楊輝三角 I
  2. https://leetcode-cn.com/problems/pascals-triangle-ii/ 楊輝三角 II

題目內容
在這裏插入圖片描述
在楊輝三角中,每個數是他的左上方和右上方的數的和,公式表達爲:
f(i,j)=f(i1,j1)+f(i1,j)(1) f(i,j) = f(i-1,j-1)+f(i-1,j) \tag{1}


題目內容

  • 楊輝三角 I: 給定一個非負整數 numRows,生成楊輝三角的前 numRows 行。

示例:

輸入: 5
輸出:
[
[1],
[1,1],
[1,2,1],
[1,3,3,1],
[1,4,6,4,1]
]

這題最直觀的方法是採用遞推式(1),根據上一行的數據直接產生下一行的數據就行了,比較簡單,見代碼:

class Solution {
public:
    vector<vector<int>> generate(int numRows) {
        // f(i,j) = f(i-1, j-1)+f(i-1,j)
        if (numRows <= 0)
            return vector<vector<int>>();
        vector<vector<int>> ret;
        ret.push_back(vector<int>{1});
        for(int layer = 1; layer < numRows; layer++){
            vector<int> tmp(layer+1);
            tmp[0] = 1;
            tmp[layer] = 1;
            for (int element = 1; element < layer; element++)
                tmp[element] = ret[layer-1][element-1]+ret[layer-1][element];
            
            ret.push_back(tmp);
        }
        return ret;
    }
};

容易知道,此代碼的時間複雜度是O(n2)\mathcal{O}(n^2),空間複雜度爲O(n2)\mathcal{O}(n^2)

如果我們輸入行數,只需要函數輸出特定行數的排列,而不需要整個前n行的排列,我們可以怎麼做呢?當然,我們可以把前n行都計算出來後,取某個行的結果,不過這樣的計算複雜度是比較高的,我們可以用一些巧妙些的方法,把計算複雜度和空間複雜度減少,見第二題。

題目內容

  • 楊輝三角II:給定一個非負索引 k,其中 k ≤ 33,返回楊輝三角的第 k 行

示例:

輸入: 3
輸出: [1,3,3,1]

注意到我們可以把第二題的空間複雜度優化到O(n)\mathcal{O}(n),針對指定的第n行,我們只需要線性空間即可。算法流程如下:我們首先初始化出一個數組,這個數組的長度爲n+1,對於任意行,總是可以把第一個數初始化爲1,假設我們的n=4,於是我們有初始化的數組[1,0,0,0],我們有如下遞推公式:

for (int i = n-1; i > 0; --i)
	v[i] = v[i]+v[i-1];

我們發現,其實是倒過來進行相鄰元素疊加的,因爲如果是正向疊加,會影響到之前的元素,操作起來比較麻煩些,而倒過來進行則不會這樣。於是有:
第一輪

step1: [1, 0, 0, 0] 初始化
step2: [1, 0, 0, 0] 空操作
step3: [1, 0, 0, 0] 空操作
step4: [1, 1, 0, 0]

第二輪

step1: [1, 1, 0, 0] 空操作
step2: [1, 2, 1, 0]

我們注意到有部分0+0的操作是空操作,是不必要的,可以去掉以提高性能。最終,我們的代碼如下所示:

class Solution {
public:
    vector<int> getRow(int rowIndex) {
        vector<int> ret(rowIndex+1);
        ret[0] = 1;
        for (int j = rowIndex; j > 0; j--)
            for (int i = rowIndex-j+1; i > 0; --i)
                ret[i] += ret[i-1];
            
        return ret;
        
    }
};

還算是比較精簡的,其時間複雜度爲O(n2)\mathcal{O}(n^2),準確的說是O(12n2)\mathcal{O}(\frac{1}{2}n^2),空間複雜度爲O(n)\mathcal{O}(n)


容易出現的問題

  1. 注意邊界,爲了減少空操作,邊界特別要注意。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章