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