数据结构与算法 -二叉树和递归算法leetcode 刷题011

今天的刷题内容是二叉树和递归的应用:

二叉树中的很多题目都可以通过递归的方法进行调用,比如简单的前序遍历,中序遍历,后续遍历等算法的实现,递归调用主要是两个内容,一个是递归的终止条件,另一个是递归循环体;废话不多说直接使用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;
    }
};



猜你喜欢

转载自blog.csdn.net/hufanglei007/article/details/79570975