LeetCode(119):楊輝三角 II


Easy!

題目描述:

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

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

示例:

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

進階:

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

解題思路:

楊輝三角想必大家並不陌生,應該最早出現在初高中的數學中,其實就是二項式系數的一種寫法。

        1
       1 1
      1 2 1
     1 3 3 1
    1 4 6 4 1
   1 5 10 10 5 1
  1 6 15 20 15 6 1
 1 7 21 35 35 21 7 1
1 8 28 56 70 56 28 8 1

楊輝三角形第n層(頂層稱第0層,第1行,第n層即第n+1行,此處n為包含0在內的自然數)正好對應於二項式\left(a+b\right)^{n}展開的系數。例如第二層1 2 1是冪指數為2的二項式\left(a+b\right)^{2}展開形式a^{2}+2ab+b^{2}的系數。

楊輝三角主要有下列五條性質:

  1. 楊輝三角以正整數構成,數字左右對稱,每行由1開始逐漸變大,然后變小,回到1。
  2. n行的數字個數為n個。
  3. n行的第k個數字為組合數C_{n-1}^{k-1}
  4. n行數字和為2^{n-1}
  5. 除每行最左側與最右側的數字以外,每個數字等於它的左上方與右上方兩個數字之和(也就是說,第n行第k個數字等於第n-1行的第k-1個數字與第k個數字的和)。這是因為有組合恆等式:C_{n}^{i}=C_{n-1}^{i-1}+C_{n-1}^{i}。可用此性質寫出整個楊輝三角形。

由於題目有額外限制條件,程序只能使用O(k)的額外空間,那么這樣就不能把每行都算出來,而是要用其他的方法,。最先考慮用的是第三條性質,算出每個組合數來生成第n行系數,代碼如下:

C++ 解法一:

 1 /**
 2  * NOT Correct!
 3  */
 4 class Solution {
 5 public:
 6     vector<int> getRow(int rowIndex) {
 7         vector<int> out;
 8         if (rowIndex < 0) return out;
 9         
10         for (int i = 0; i <= rowIndex; ++i) {
11             if ( i == 0 || i == rowIndex)
12                 out.push_back(1);
13             else
14                 out.push_back (computeCnk(rowIndex, i));
15         }
16         return out;
17     }
18     
19     int computeCnk(int n, int k) {
20         if (k > n) return 0;
21         else if (k > n/2) k = n - k;
22         int numerator = 1, denomator = 1;
23         for (int i = 0; i < k; ++i) {
24             numerator *= n - i;
25             denomator *= k - i;
26         }
27         if (denomator != 0) return numerator/denomator;
28         else return 0;
29     }
30 };

本地調試輸出前十行,沒啥問題,拿到OJ上測試,程序在第18行跪了,中間有個系數不正確。那么問題出在哪了呢,仔細找找,原來出在計算組合數那里,由於算組合數時需要算連乘,而整形數int的數值范圍只有-32768到32768之間,那么一旦n值過大,連乘肯定無法計算。而喪心病狂的OJ肯定會測試到成百上千行,所以這個方法不行。那么我們再來考慮利用第五條性質,除了第一個和最后一個數字之外,其他的數字都是上一行左右兩個值之和。那么我們只需要兩個for循環,除了第一個數為1之外,后面的數都是上一次循環的數值加上它前面位置的數值之和,不停地更新每一個位置的值,便可以得到第n行的數字。

C++ 解法二:

 1 class Solution {
 2 public:
 3     vector<int> getRow(int rowIndex) {
 4         vector<int> out;
 5         if (rowIndex < 0) return out;
 6         
 7         out.assign(rowIndex + 1, 0);
 8         for (int i = 0; i <= rowIndex; ++i) {
 9             if ( i == 0) {
10                 out[0] = 1;
11                 continue;
12             }
13             for (int j = rowIndex; j >= 1; --j) {
14                 out[j] = out[j] + out[j-1];
15             }
16         }
17         return out;
18     }
19 };

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM