递归
递归的基本思想就是程序反复调用自身
如果搞不清楚递归,那大多是犯了这个错误:纠结递归本层做了什么,下一层又做了什么,导致我们把递归想的复杂化。实际上,递归是一个反复调用自身的程序,那么就说明每层递归的作用都是一样的,因此我们只需要关注一级递归的解决过程即可
那么对于一级递归,我们需要关心的主要是以下三点:
- 整个递归的终止条件。
- 这一级递归需要做什么?
- 应该返回给上一级的返回值是什么?
于是我们将会又这三个目标,即递归三部曲
- 找整个递归的终止条件:递归应该在什么时候结束?
- 找返回值,确定函数参数:应该给上一级返回什么信息?
- 本级递归应该做什么:在这一级递归中,应该完成什么任务?
下面我将拿实际题目来讲解递归 ,帮助读者更好的理解递归
226. 翻转二叉树
本题是考查对二叉树的操作和理解的一题题目,考查了我们对二叉树三种遍历顺序(前中后序遍历)的掌握,以及我们对二叉树的递归法遍历的掌握。
1.确定递归函数的终止条件:
很显然,当节点为空时,就返回;
2.确定传入的参数和返回值:
传入的参数当然是节点,也就是TreeNode* root ,当然有的时候我们无法确定函数的参数数量,那么我们先写着,等需要的时候再补上就行
返回值类型也是TreeNode*
3.确定本层递归需要时做的事:交换两个节点的位置,这里又考查到了二叉树的前中后序遍历,我们这里如果采用前序遍历,那么单层递归的写法就是
swap(root->left, root->right);//中
invertTree(root->left);//左
invertTree(root->right);//右
那么当这三步走完之后,整体代码也就显而易见了
具体代码如下:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
TreeNode* invertTree(TreeNode* root) {
if(root==NULL) return root;
swap(root->left,root->right);
invertTree(root->left);
invertTree(root->right);
return root;
}
};
101. 对称二叉树
那么这题题目用递归法如何解决?
还是老样子,先思考递归三部曲:
1.确定函数参数以及返回值:
函数返回值为bool型,函数参数暂时不明,也不急着确定,先放着
2.确定递归的终止条件:
那么对于这题对称二叉树而言,什么时候应该是一层递归的终止?三种节点的情况:1.左节点为空,右节点不为空 2.左节点不为空,右节点为空 3.左右节点皆为空时。还有一种节点内值的情况,如果左右节点相等,那么返回true
3.确定一层递归的逻辑:
比较二叉树两边的内侧节点是否对称
比较二叉树两边的外侧节点是否对称
如果两边都对称,那么返回true 否则返回false;本题只有使用后序遍历是能完成我上述的步骤的
那么思考完第三步,我们可以思考并确认传入的参数了,要比较二叉树两边的内侧和外侧,我们则需要一个指针和一个右指针,分别拿这两个指针来对比
所以在第一步确定函数参数时我们可以写两个参数(TreeNode* left,TreeNode* right)
具体完整代码如下:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:确定返回值和函数参数
bool comparison(TreeNode* left,TreeNode* right){
确定终止条件
if(left==NULL&&right!=NULL) return false;
else if(left!=NULL&&right==NULL) return false;
else if(left==NULL&&right==NULL) return true;
else if(left->val!=right->val) return false;
单层逻辑
return comparison(left->left,right->right)&&comparison(left->right,right->left);
}
bool isSymmetric(TreeNode* root) {
if(root==NULL) return true;
return comparison(root->left,root->right);
}
};
看完了上面两个题目,相信大家对递归也有了一定的理解,下面我来讲二叉树的层序遍历:
二叉树的层序遍历:
102. 二叉树的层序遍历
层序遍历,就是BFS,逐层的遍历二叉树
对于层序遍历,我们可以使用队列这一数据结构,利用他先进后出的特点,来层序遍历二叉树
具体代码如下
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>>result;
queue<TreeNode*>que;
if(root!=NULL) que.push(root);
while(!que.empty()){
int size=que.size();
vector<int>vec;
for(int i=0;i<size;i++){
TreeNode* node=que.front();
que.pop();
vec.push_back(node->val);
if (node->left) que.push(node->left);
if (node->right) que.push(node->right);
}
result.push_back(vec);
}
return result;
}
};