【leetcode/數組和字符串】楊輝三角形(滾動數組 大數字乘法思考)

問題描述:

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

在楊輝三角中,每個數是它左上方和右上方的數的和。

示例:

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

進階:

你可以優化你的算法到 O(k) 空間複雜度嗎?

基本思路:

一開始我的想法就是利用楊輝三角形和排列組合公式相結合。

爲了存儲我的結果我確實需要O(k)的空間。

但是這樣超出了long long的範圍。(算階乘的時候signed integer overflow了,其實完全沒有必要算到這麼大

於是考慮時間換空間的做法。

(附signed integer overflow的代碼)

class Solution {
public:
    long long C(int m, int n) {   // m > n
      long long up = 1;
      long long down = 1;
      for (int i = 0; i < n; ++i) {
        up *= (m - i);
        down *= (i + 1);
      }
      return up / down;
    }
    vector<int> getRow(int rowIndex) {
      vector<int> res;
      for (int i = 0; i <= rowIndex; ++i) {
        res.push_back(C(rowIndex, i));
      }
      return res;
    }
};

注意到可以使用滾動數組的思想。

即每一層遍歷的時候還是使用同樣的數組,但是要經過一定的技巧使我們要用到的元素不會被提前覆蓋掉

觀察得如果我們從後往前覆蓋數組,之前必須的元素就不會被覆蓋掉。

和以上算法的對比就在於我們不得不一層一層地計算得到。

AC代碼:

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

其他經驗:

  1.  使用滾動數組的思想重複利用空間。
  2.  注意滾動數組中覆蓋的順序,不要讓我們需要使用到的元素被提前覆蓋了。
  3.  做稍微大一點數字的乘法的時候注意signed integer overflow的錯誤。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章