今天的刷题内容是二叉树和递归的应用:
二叉树中的很多题目都可以通过递归的方法进行调用,比如简单的前序遍历,中序遍历,后续遍历等算法的实现,递归调用主要是两个内容,一个是递归的终止条件,另一个是递归循环体;废话不多说直接使用leetcode中的题来练手
leetcode104,求一个二叉树的最大深度,
class Solution {
public:
int maxDepth(TreeNode* root) {
if(root==NULL){
return 0;//递归的停止条件
}
int left_max=maxDepth(root->left);
int right_max=maxDepth(root->right);
return max(left_max,right_max)+1;
}
};
提交后运行的时间为8ms;
最大深度还可以通过层序遍历的方式,还可以通过dfs的方式来实现
层序遍历的代码如下:
int maxDepth(TreeNode* root) {
//方法一使用层序遍历的方式 进行 统计相应的层数
//方法二 使用的是递归的方式进行相应的统计 非递归方式统树的高度
//方法三采用dfs的方式 深度搜索的方式
if(root==NULL){
return 0;
}
queue<TreeNode*> qq;
qq.push(root);
int step=0;
while(!qq.empty()){
int size=qq.size();
int i=0;
while(i<size){
TreeNode* node=qq.front();
qq.pop();
if(node->left){
qq.push(node->left);
}
if(node->right){
qq.push(node->right);
}
i++;
}
step++;
}
return step;
}
采用dfs的方式代码如下:
int maxDepth(TreeNode* root){
if(root==NULL){
return 0;
}
int length=dfs(root);
return length;
}
int dfs(TreeNode* root){
if(root==NULL){
return 0;
}
int l=dfs(root->left);
int r=dfs(root->right);
return max(l,r)+1;
}
类似的Leetcode111
class Solution {
public:
int minDepth(TreeNode* root) {
//求解二叉树中最小深度
if(root==NULL){
return 0;
}
// int left_num=minDepth(root->left);
// int right_num=minDepth(root->right);
// return min(left_num,right_num)+1;
//如果直接使用这样的递归算法,会导致出错,原因就是 题目要求是从根节点到叶子节点的路径,对于不平衡的树会导致出错,递归的停止条件需要改变
if(root->left==NULL&&root->right==NULL){
return 1;
}
if(root->left==NULL&&root->right!=NULL){
return minDepth(root->right)+1;
}
if(root->right==NULL&&root->left!=NULL){
return minDepth(root->left)+1;
}
int left_num=minDepth(root->left);
int right_num=minDepth(root->right);
return min(left_num,right_num)+1;
}
};
leetcode226:反转一棵二叉树;
class Solution {
public:
TreeNode* invertTree(TreeNode* root) {
if(root==NULL){
return NULL;//书写循环终止条件
}
// if(root->left==NULL&&root->right==NULL){
// return root;
// }不需要添加 因为返回的就是root
// TreeNode* tree_left=root->left;
// TreeNode* tree_right=root->right;
invertTree(root->left);
invertTree(root->right);
swap(root->left,root->right);
return root;
}
};
leetcode100:判断两棵树是否是一样的树;
class Solution {
public:
bool isSameTree(TreeNode* p, TreeNode* q) {
//递归调用来实现,或者是采用先序遍历方式来实现保存至一个vector中,然后实现
//递归的终止条件
if(p==NULL&&q==NULL){
return true;
}
if(p==NULL||q==NULL){
return false;
}
if(p->val!=q->val){
return false;
}
if((isSameTree(p->left,q->left))&&isSameTree(p->right,q->right)){
return true;
}
return false;
}
};
leetcode101:判断一棵树是否是对称树;
class Solution {
public:
bool isSymmetric(TreeNode* root) {
//采用递归的方法来实现;
//首先是循环的停止条件
if(root==NULL){
return true;
}
if(root->left==NULL&&root->right==NULL){
return true;
}
if(root->left==NULL||root->right==NULL){
return false;
}
return isSymmetric2(root->left,root->right);
}
bool isSymmetric2(TreeNode* left,TreeNode* right){
if(left==NULL&&right==NULL){
return true;
}
if(left==NULL||right==NULL){
return false;
}
if(left->val!=right->val){
return false;
}
return isSymmetric2(left->left,right->right)&&isSymmetric2(left->right,right->left);
}
};
leetcode110:判断一棵树是否是平衡树,什么是平衡树(平衡树就是每一层的两个结点的深度最大相差1);
class Solution {
public:
bool isBalanced(TreeNode* root) {
//首先递归的停止条件
if(root==NULL){
return true;
}
if(root->left==NULL&&root->right==NULL){
return true;
}
//得到每个结点的从根节点到叶节点的路径长度;
int left_num=length(root->left);
int right_num=length(root->right);
if(abs(left_num-right_num)==1||abs(left_num-right_num)==0){
return isBalanced(root->left)&&isBalanced(root->right);//如果当前层是平衡树,那么继续比较下一层
}
else{
return false;
}
}
int length(TreeNode * root){
if(root==NULL){
return 0;
}
int leftNum=length(root->left);
int rightNum=length(root->right);
return max(leftNum,rightNum)+1;
}
};
leetcode112: 判断是否有路径和为sum的路径;最主要的就是书写递归停止的条件;
class Solution {
public:
bool hasPathSum(TreeNode* root, int sum) {
//递归的停止条件
if(root==NULL){
return false;
}
if(root->left==NULL&&root->right==NULL&&root->val==sum){
return true;
}
if(root->left==NULL&&root->right==NULL&&root->val!=sum){
return false;
}
if((root->left==NULL||root->right==NULL)&&root->val==sum){
return false;
}
return hasPathSum(root->left,sum-root->val)||hasPathSum(root->right,sum-root->val);
}
};
leetcode222:求一个完全二叉树的结点的个数;
首先需要知道什么是完全二叉树:
class Solution {
public:
int countNodes(TreeNode* root) {
//什么是完全二叉树,完全二叉树是指除了最下面一层,其余层的结点都是满的,最下面一层的二叉树分布在最左边的位置处;
//循环停止条件
// if(root==NULL){
// return 0;
// }
// if(root->left==NULL&&root->right==NULL){
// return 1;
// }
// if(root->left==NULL||root->right==NULL){
// return 2;
// }
// return countNodes(root->left)+countNodes(root->right)+1;//这个方法没有体现完全二叉树的特性,所以没有accept,原因在于过多的递归导致系统栈溢出
if(root==NULL)
return 0;
int leftDepth=0;
int rightDepth=0;
for(TreeNode* node=root;node!=NULL;node=node->left)
leftDepth++;
for(TreeNode* node=root;node!=NULL;node=node->right)
rightDepth++;
if(leftDepth==rightDepth)
return (1<<leftDepth)-1;
else
return countNodes(root->left)+countNodes(root->right)+1;
}
};
leetcode404:计算出所有左子节点的和,这道题的递归条件有所不同,所以递归的停止条件比较复杂;刚开始的时候没有想出来;
class Solution {
public:
int sumOfLeftLeaves(TreeNode* root) {
if(root==NULL){
return 0;
}
if(root->left!=NULL&&root->left->left==NULL&&root->left->right==NULL){
return root->left->val+sumOfLeftLeaves(root->right);
}
return sumOfLeftLeaves(root->left)+sumOfLeftLeaves(root->right);
}
};
leetcode 257: 从递归中返回一个vector类型的数据结构的递归问题;
class Solution {
public:
vector<string> binaryTreePaths(TreeNode* root) {
//相对比较复杂的递归停止条件的习题
//可以知道原函数的递归的返回值是vector类型的数据,所以每一次返回的都是vector<string>数据
vector<string> ans;
if(root==NULL){
return ans;
}
if(root->left==NULL&&root->right==NULL){
ans.push_back(to_string(root->val));
return ans;
}
vector<string> left_string=binaryTreePaths(root->left);
vector<string> right_string=binaryTreePaths(root->right);
for(int i=0;i<left_string.size();i++){
ans.push_back(to_string(root->val)+"->"+left_string[i]);
}
for(int j=0;j<right_string.size();j++){
ans.push_back(to_string(root->val)+"->"+right_string[j]);
}
return ans;
}
};
leetcode113:这道题是上一道题的扩展,只不过这道题的是求出相应的路径,并且是使用vector,操作上会有一点麻烦,而且还必须是从根节点到叶子节点的路径;递归的停止条件比较复杂;
class Solution {
public:
vector<vector<int>> pathSum(TreeNode* root, int sum) {
vector<vector<int>> ans;
if(root==NULL){
return ans;
}
vector<int> temp;
if(root->left==NULL&&root->right==NULL&&root->val==sum){
temp.push_back(root->val);
ans.push_back(temp);
return ans;
}
if((root->left==NULL)&&root->val!=sum){//如果找不到要怎么办,首先需要书写一个函数判断一下
vector<vector<int>> right_ans=pathSum(root->right,sum-root->val);
for(int i=0;i<right_ans.size();i++){
vector<int> temp=right_ans[i];
vector<int>::iterator it=temp.begin();
temp.insert(it,root->val);
ans.push_back(temp);
}
return ans;
}
if((root->right==NULL)&&root->val!=sum){//如果找不到要怎么办,首先需要书写一个函数判断一下
vector<vector<int>> left_ans=pathSum(root->left,sum-root->val);
for(int i=0;i<left_ans.size();i++){
vector<int> temp=left_ans[i];
vector<int>::iterator it=temp.begin();
temp.insert(it,root->val);
ans.push_back(temp);
}
return ans;
}
vector<vector<int>> right_ans2=pathSum(root->right,sum-root->val);
for(int i=0;i<right_ans2.size();i++){
vector<int> temp=right_ans2[i];
vector<int>::iterator it=temp.begin();
temp.insert(it,root->val);
ans.push_back(temp);
}
vector<vector<int>> left_ans2=pathSum(root->left,sum-root->val);
for(int i=0;i<left_ans2.size();i++){
vector<int> temp=left_ans2[i];
vector<int>::iterator it=temp.begin();
temp.insert(it,root->val);
ans.push_back(temp);
}
return ans;
}
};