N位階梯數的個數 - 空間最佳化方案


在本文中,我們將學習階梯數。我們將使用多種C++技術來查詢也是階梯數的N位數的可能個數。我們還將討論最節省空間的解決方案。

讓我們首先討論階梯數。這些數字的相鄰數字之間的差為1。例如,321 - 每個相鄰數字 (3, 2, 1) 的差都連續為1。

在這裡,我們將給出N的值,然後我們必須找到所有N位階梯數的個數。

輸入輸出場景

給定N,輸出為N位階梯數的個數。

Input: N = 3
Output: 32
Input: N = 4
Output: 61

對於N = 3,可能的階梯數是32。這些數字是101、121、123、210、212、232、234、321等等。

使用迭代

我們將迭代所有N位數,並檢查它們是否是階梯數。

  • 首先,我們建立一個名為steppingNumber的函式,用於檢查一個數是否是階梯數。這是一個布林函式,所以它返回true或false。

  • 在這個函式中,我們使用to_string()將數字轉換為字串。然後,我們迭代所有數字,並找到每個數字之間的差。如果差值不為1,則返回false。否則,結果為true。

  • 接下來,我們建立函式來計算階梯數。在這個函式中,我們從第一個N位數迭代到最後一個N位數。對於每個數字,我們應用steppingNumber函式。如果函式返回true,則變數count加1。

示例

讓我們看一個例子:

#include <iostream>
#include <cmath>
using namespace std;
bool steppingNumber(int i) {
   string numStr = to_string(i);
   for (int j = 1; j < numStr.length(); j++) {
      int diff = abs(numStr[j] - numStr[j - 1]);
      if (diff != 1) {
         return false;
      }
   }
   return true;
}
int possibleNumbers(int N) {
   int begin = pow(10, N - 1);
   int end = pow(10, N) - 1;
   int count = 0;
   for (int i = begin; i <= end; i++) {
      if (steppingNumber(i)) {
         count++;
      }
   }
   return count;
}
int main() {
   int N = 3;
   cout << "Number of " << N << " digit stepping numbers are " <<
   possibleNumbers(N);
   return 0;
}

輸出

Number of 3 digit stepping numbers are 32

注意 - 這種方法非常簡單,效率不高。它會進行冗餘計算,並且耗時更長。

使用空間最佳化方法

在這裡,我們使用這樣一個概念:在階梯數中,每個數字都比前一個數字大1或小1。

  • 我們有兩個陣列,它們分別儲存N位階梯數和(N – 1)位階梯數的個數。

  • 我們從2迴圈到N。在這個迴圈中,我們執行兩個for迴圈,每個迴圈從0到9(因為數字可以在0-9之間)。對於每個數字,我們使用currentCount陣列的值更新previousCount陣列的值。

  • 如果(k > 0),我們將previousCount[k – 1]的值新增到currentCount陣列。這是因為如果第一個數字等於(k – 1),則將1加到(N – 1)位數字的第一個數字會得到N位階梯數。

  • 如果(k < 9),我們將previousCount[k + 1]的值新增到currentCount陣列。這是因為如果第一個數字等於(k + 1),則將1加到(N – 1)位數字的第一個數字會得到N位階梯數。

  • 接下來,我們新增currentCount陣列的值之和。

示例

以下是一個例子:

#include <iostream>
using namespace std;
int possibleNumbers(int N) {
   int previousCount[10] = {0};
   int currentCount[10] = {1, 1, 1, 1, 1, 1, 1 ,1, 1, 1};
   for (int j = 2; j <= N; ++j) {
      for (int k = 0; k <= 9; ++k) {
         previousCount[k] = currentCount[k];
         currentCount[k] = 0;
      }
      for (int k = 0; k <= 9; ++k) {
         if (k > 0)
         currentCount[k] += previousCount[k - 1];
         if (k < 9)
         currentCount[k] += previousCount[k + 1];
      }
   }
   int count = 0;
   for (int k = 1; k <= 9; ++k) {
      count += currentCount[k];
   }
   return count;
}
int main() {
   int N = 5;
   cout << "Number of " << N << " digit stepping numbers are " <<
   possibleNumbers(N);
   return 0;
}

輸出

Number of 5 digit stepping numbers are 116

使用動態規劃方法

我們將使用單個一維陣列來儲存計算結果,而不是使用兩個一維陣列(如前面的方法)。

示例

#include <iostream>
#include <vector>
using namespace std;
long long possibleNumbers(int N){
   vector<long long> dp(10, 1);
   if (N == 1)
   return 10;
   for (int i = 2; i <= N; i++) {
      vector<long long> new_dp(10, 0);
      new_dp[0] = dp[1];
      new_dp[9] = dp[8];
      for (int j = 1; j <= 8; j++)
      new_dp[j] = dp[j - 1] + dp[j + 1];
      dp = new_dp;
   }
	long long totalCount = 0;
	for (int j = 1; j <= 9; j++)
	totalCount += dp[j];
	return totalCount;
}
int main(){
   int N = 4;
   cout << "Number of " << N << " digit stepping numbers are " <<
   possibleNumbers(N);
   return 0;
}

輸出

Number of 4 digit stepping numbers are 61

結論

我們討論了查詢N位階梯數個數的不同方法。第一種方法是使用迭代的簡單方法。第二種方法使用兩個一維陣列來儲存計算結果,是一種空間最佳化的方案。在第三種方法中,我們使用單個一維陣列代替兩個這樣的陣列,這使得程式碼效率更高。

更新於:2024年1月5日

瀏覽量:122

開啟你的職業生涯

完成課程獲得認證

開始學習
廣告