递归的基本思想是某个函数直接或者间接地调用自身,这样就把原问题的求解转换为许多性质相同但是规模更小的子问题。我们只需要关注如何把原问题划分成符合条件的子问题,而不需要去研究这个子问题是如何被解决的。递归和枚举的区别在于:枚举是横向地把问题划分,然后依次求解子问题,而递归是把问题逐级分解,是纵向的拆分
递归三要素
1、明确递归终止条件;
2、给出basecase的处理办法;
3、提取重复的逻辑,找出函数的等价关系式。
斐波那契数列
斐波那契数列是一位意大利的数学家,他闲着没事去研究兔子繁殖的过程,研究着就发现,可以写成这么一个序列:1,1,2,3,5,8,13,21… 也就是每个数等于它前两个数之和。那么给你第 n 个数,问 F(n) 是多少。
解析
三步:
递归终止条件:f(0)=1,f(1)=1;
basecase返回:f(0)=1,f(1)=1;
函数关系:f(n)=f(n-1)+f(n-2);
class Solution {
public int fib(int N) {
if (N == 0) {
return 0;
} else if (N == 1) {
return 1;
}
return fib(N-1) + fib(N-2);
}
}
二叉树的前序遍历
解析
三步:
递归终止条件:root==NULL;
basecase返回:root->val;
函数关系:preorderTraversal(root->root);preorderTraversal(root->right);
class Solution {
public:
vector<int> ans;
vector<int> preorderTraversal(TreeNode* root) {
if(root != NULL){
ans.push_back(root -> val);
preorderTraversal(root -> left);
preorderTraversal(root -> right);
}
return ans;
}
};
二叉树的中序遍历
解析
三步:
递归终止条件:root==NULL;
basecase返回:root->val,nose=root->right,inorderTraversal(root->right);
函数关系:inorderTraversal(root->left)
vector<int> results;
vector<int> inorderTraversal(TreeNode* root) {
traverse(root);
return results;
}
void traverse(TreeNode* node){
if(node==NULL) return;
traverse(node->left);
results.push_back(node->val);
traverse(node->right);
}
二叉树的后序遍历
解析
三步:
递归终止条件:root==NULL;
basecase返回:root->val;
函数关系:postorderTraversal(root->left); postorderTraversal(root -> right);
class Solution {
public:
vector<int> ans;
vector<int> postorderTraversal(TreeNode* root) {
if(!root) return ans;
postorderTraversal(root -> left);
postorderTraversal(root -> right);
ans.push_back(root -> val);
return ans;
}
};