递归实现
实现递归编程的方法,需要三步(第2和第3可以同时思考):
- 明确函数作用是什么
- 递归的条件表达式
- 递归结束的条件
用三个具体的例子做具体分析:
- 计算n的阶乘
- 斐波那契数列
- 查找二叉树最大的节点
example 1: 计算n的阶乘
Q1:函数作用是什么?
计算n的阶乘,返回结果—— 确定函数及返回值
long long factorial(int n) {
long long res;
return res;
}
Q2:递归的条件表达式
factorial(n) = factorial(n-1)*n
long long factorial(int n) {
long long res;
res = factorial(n-1)*n;
return res;
}
Q3: 递归结束的条件
factorial(1) = 1;
long long factorial(int n) {
long long res;
if (n==1)
return 1;
res = factorial(n-1)*n;
return res;
}
最后,对代码进行一下整理
long long factorial(int n) {
if (n==1)
return 1;
return factorial(n-1)*n;
}
example 2: 斐波那契数列
Q1:函数作用是什么?
计算斐波那契数列第n个数,返回结果—— 确定函数及返回值
int fibonacci(int n) {
return;
}
Q2:递归的条件表达式
fibonacci(n) = fibonacci(n-1) + fibonacci(n-2)
int fibonacci(int n) {
return fibonacci(n-1) + fibonacci(n-2);
}
Q3: 递归结束的条件
fibonacci(1) = 1;
fibonacci(2) = 1;
int fibonacci(int n) {
if (n==1)
return 1;
if (n==2)
return 1;
return fibonacci(n-1) + fibonacci(n-2);
}
注意:这里只是用fibonacci数列作为例子,实际开发中fibonacci求结果不应该使用递归来实现。因为在递归过程中,太多运算被重复,时间复杂度变得很夸张,不推荐使用。
example 3: 查找二叉树最大的节点
Q1:函数作用是什么?
找到二叉树最大节点,返回这个节点—— 确定函数及返回值
class TreeNode {
public:
int val;
TreeNode* left, * right;
TreeNode(int val) {
this->val = val;
this->left = this->right = NULL;
}
};
TreeNode* maxNode(TreeNode* root) {
return node;
}
Q2:递归的条件表达式
遍历左子树,找到最大值。
遍历右子树,找到最大值。
比较root,左子树最大值,右子树最大值
class TreeNode {
public:
int val;
TreeNode* left, * right;
TreeNode(int val) {
this->val = val;
this->left = this->right = NULL;
}
};
TreeNode* maxNode(TreeNode* root) {
TreeNode* left = maxNode(root->left);
TreeNode* right = maxNode(root->right);
return max(root, max(left, right));
}
Q3: 递归结束的条件
当某一节点为NULL时,即其父节点到底,开始回归。
class TreeNode {
public:
int val;
TreeNode* left, * right;
TreeNode(int val) {
this->val = val;
this->left = this->right = NULL;
}
};
TreeNode* maxNode(TreeNode* root) {
if (root == NULL)
return root;
TreeNode* left = maxNode(root->left);
TreeNode* right = maxNode(root->right);
return max(root, max(left, right));
}
上面的代码,部分是伪代码,进行细节优化
class TreeNode {
public:
int val;
TreeNode* left, * right;
TreeNode(int val) {
this->val = val;
this->left = this->right = NULL;
}
};
TreeNode* maxNode(TreeNode* root) {
if (root == NULL)
return root;
TreeNode* left = maxNode(root->left);
TreeNode* right = maxNode(root->right);
return max(root, max(left, right));
}
TreeNode* max(TreeNode* a, TreeNode* b) {
//考虑左节点为NULL
if (a == NULL)
return b;
//考虑右节点为NULL
if (b == NULL)
return a;
//考虑左右节点都不为NULL
if (a->val > b->val) {
return a;
}
return b;
}
对于上面的max函数,未考虑左右节点均为NULL情况,看一下原因:
当这种状况出现时, max(left, right)) 返回NULL。
然后执行,max(root, NULL),root肯定不为NULL,所以不会出现故障报错。<root为NULL时,程序不会执行到这里>