杨辉三角(Pascal's Triangle)是一个经典的数学问题,也可以用递归算法来生成。下面是一个使用C++递归计算杨辉三角指定行列值的代码示例。
普通递归
#include <iostream>
using namespace std;
// 计算杨辉三角中指定行列的值
int pascal(int row, int col) {
// 递归基例:如果是第一列或对角线上的元素,值为1
if (col == 0 || col == row) {
return 1;
}
// 递归关系:每个位置的值等于它上面两个位置的值之和
return pascal(row - 1, col - 1) + pascal(row - 1, col);
}
int main() {
int rows;
cout << "请输入杨辉三角的行数: ";
cin >> rows;
// 打印杨辉三角
for (int i = 0; i < rows; ++i) {
for (int j = 0; j <= i; ++j) {
cout << pascal(i, j) << " ";
}
cout << endl;
}
return 0;
}
代码解析:
-
函数
pascal
:- 递归基例:如果
col
为0
(第一列)或col == row
(对角线上的元素),返回1
。 - 递归关系:每个位置的值等于它上面两个位置的值之和,即
pascal(row - 1, col - 1) + pascal(row - 1, col)
。
- 递归基例:如果
-
主函数
main
:- 用户输入杨辉三角的行数
rows
,然后通过双重循环调用pascal
函数来生成并打印每一行的值。
- 用户输入杨辉三角的行数
运行结果示例:
假设输入5
行,输出为:
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
记忆化递归(二维)
使用记忆化递归或动态规划可以显著优化计算杨辉三角的效率,避免重复计算相同的子问题。下面是改进后的C++代码,使用动态规划思想来生成杨辉三角。
#include <iostream>
#include <vector>
using namespace std;
// 计算杨辉三角中指定行列的值,使用动态规划进行优化
int pascal(int row, int col, vector<vector<int>>& dp) {
// 如果已经计算过该值,直接返回
if (dp[row][col] != -1) {
return dp[row][col];
}
// 递归基例:如果是第一列或对角线上的元素,值为1
if (col == 0 || col == row) {
dp[row][col] = 1;
} else {
// 递归关系:每个位置的值等于它上面两个位置的值之和
dp[row][col] = pascal(row - 1, col - 1, dp) + pascal(row - 1, col, dp);
}
return dp[row][col];
}
int main() {
int rows;
cout << "请输入杨辉三角的行数: ";
cin >> rows;
// 初始化二维向量用于存储已经计算过的值,初始值设为-1表示未计算
vector<vector<int>> dp(rows, vector<int>(rows, -1));
// 打印杨辉三角
for (int i = 0; i < rows; ++i) {
for (int j = 0; j <= i; ++j) {
cout << pascal(i, j, dp) << " ";
}
cout << endl;
}
return 0;
}
代码解析:
-
动态规划数组
dp
:dp
是一个二维向量,大小为rows x rows
,初始值设为-1
表示该位置尚未计算。
-
函数
pascal
:- 在递归计算之前,首先检查
dp[row][col]
是否已经计算过。如果已经计算过,直接返回该值,避免重复计算。 - 如果还未计算,则按照递归关系计算,并将结果存储在
dp[row][col]
中。
- 在递归计算之前,首先检查
-
主函数
main
:- 用户输入行数
rows
,然后初始化dp
数组。 - 通过双重循环调用
pascal
函数生成并打印杨辉三角。
- 用户输入行数
运行结果示例:
同样的输入5
行,输出结果仍然是:
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
优化效果:
通过引入记忆化(使用dp
数组存储已经计算过的值),大大减少了递归的重复计算,提升了算法的效率,尤其在处理较大规模的杨辉三角时效果更为明显。
记忆化递归(一维)
通过只存储当前行和前一行的数据,可以减少空间复杂度,并且在每次计算新的一行时更新数组中的值。下面是使用一维数组进行优化的C++代码:
#include <iostream>
#include <vector>
using namespace std;
int main() {
int rows;
cout << "请输入杨辉三角的行数: ";
cin >> rows;
// 初始化一维向量用于存储当前行的值
vector<int> dp(rows, 1); // 每行的第一个元素始终为1
// 打印杨辉三角
for (int i = 0; i < rows; ++i) {
// 从后往前更新数组中的值,避免覆盖未更新的值
for (int j = i - 1; j > 0; --j) {
dp[j] = dp[j] + dp[j - 1];
}
// 打印当前行
for (int j = 0; j <= i; ++j) {
cout << dp[j] << " ";
}
cout << endl;
}
return 0;
}
代码解析:
-
一维向量
dp
:dp
数组用于存储杨辉三角当前行的数据,初始化大小为rows
,所有元素初始值为1
,因为每行的第一个和最后一个元素总是1
。
-
更新
dp
数组:- 计算每一行时,从后往前更新
dp
数组,计算新的dp[j]
值时,依赖于前一行的dp[j]
和dp[j-1]
。这样可以避免覆盖未更新的值。
- 计算每一行时,从后往前更新
-
主函数
main
:- 用户输入行数
rows
,然后通过循环依次计算每一行的值并打印。
- 用户输入行数
运行结果示例:
假设输入5
行,输出结果为:
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
优化效果:
使用一维数组优化后,空间复杂度从O(n^2)
降低到O(n)
。每次只需要存储当前行的值,并且通过从后往前的更新方式,避免了覆盖未使用的旧值。对于生成杨辉三角的任务,这种方法既节省了空间,又保持了计算的正确性。