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

开启你的职业生涯

完成课程获得认证

开始学习
广告