【LeetCode】二叉树以及二叉树递归相关问题汇总

二叉树相关

  • 二叉树的天然递归结构
    • 104. 二叉树的最大深度
      • 题目描述
      • 题解
    • 111. 二叉树的最小深度
      • 题目描述
      • 题解 注意终止条件必须是叶子节点 左右子树为空
      • 题解2 简化代码
      • 题解3
  • 简单的二叉树递归问题
    • 226. 翻转二叉树
      • 题目描述
      • 题解1 先交换左右节点的位置再反转节点
      • 题解2 先反转左右节点 再交换位置
    • 100. 相同的树
      • 题目描述
      • 题解1 判断左右节点是否相同并且root值相同
      • 题解2 化简代码
    • 101. 对称二叉树
      • 题目描述
      • 题解1 左子树反转后和右子树相同
      • 题解2 右子树等于左子树 左子树等于右子树 根节点值相等
    • 222. 完全二叉树的节点个数
      • 题目描述
      • 题解1 计算每个节点的个数(没有用的完全二叉树的性质)
      • 题解2 计算二叉树的层数
      • 题解3 二分查找
    • 110. 平衡二叉树
      • 题目描述
      • 题解1
      • 题解2
      • 题解3 优化 提前返回
  • 注意递归的终止条件
    • 112. 路径总和
      • 题目描述
      • 题解 看左节点有没有sum-val的路径
    • 404. 左叶子之和
      • 题目描述
      • 题解
  • 定义递归问题
    • 257. 二叉树的所有路径
      • 题目描述
      • 题解1 终止条件 必须是叶子节点
      • 题解2
      • 题解3 使用栈
    • 113. 路径总和 II
      • 题目描述
      • 方法1 递归
      • 方法2 用栈模仿递归
    • 129. 求根到叶子节点数字之和
      • 题目描述
      • 题解
  • 复杂的二叉树递归问题
    • 437. 路径总和 III
      • 题目描述
      • 题解 分为包含当前节点和不包含当前节点 两种递归情况

二叉树的天然递归结构

104. 二叉树的最大深度

题目描述

【LeetCode】二叉树以及二叉树递归相关问题汇总_第1张图片

题解

左子树的最大深度+右子树的最大深度+1

   int maxDepth(TreeNode* root) {
        if(root==NULL)
        {
            return 0;
        }
        return max(maxDepth(root->left),maxDepth(root->right))+1;
    }

111. 二叉树的最小深度

题目描述

【LeetCode】二叉树以及二叉树递归相关问题汇总_第2张图片

题解 注意终止条件必须是叶子节点 左右子树为空

注意左右子树不存在的情况 并且计算深度的起始点需要是叶子节点

    int minDepth(TreeNode* root) {
        if(root==NULL)return 0;
        if(root->left==NULL)return minDepth(root->right)+1;
        if(root->right==NULL)return minDepth(root->left)+1;
        return min(minDepth(root->left),minDepth(root->right))+1;
    }

题解2 简化代码

    int minDepth(TreeNode* root) {
        if(root==NULL)return 0;
        if(root->left==NULL||root->right==NULL)
        return max(minDepth(root->left),minDepth(root->right))+1;
        return min(minDepth(root->left),minDepth(root->right))+1;
    }

题解3

    int minDepth(TreeNode* root) {
        if (!root) return 0;  //递归结束
        int left = minDepth(root->left);  
        int right = minDepth(root->right);
        if (!left || !right) return left + right + 1;  //如果有一个空,则+1
        return min(left, right) + 1;  //否则最小值+1
    }

简单的二叉树递归问题

226. 翻转二叉树

题目描述

【LeetCode】二叉树以及二叉树递归相关问题汇总_第3张图片

题解1 先交换左右节点的位置再反转节点

    TreeNode* invertTree(TreeNode* root) {
        if(root==NULL)return NULL;
        swap(root->left,root->right);
        root->left=invertTree(root->left);
        root->right=invertTree(root->right);
        return root;
    }

题解2 先反转左右节点 再交换位置

    TreeNode* invertTree(TreeNode* root) {
        if(root==NULL)return NULL;
        
        invertTree(root->left);
        invertTree(root->right);
        swap(root->left,root->right);
        return root;
    }

100. 相同的树

题目描述

【LeetCode】二叉树以及二叉树递归相关问题汇总_第4张图片

题解1 判断左右节点是否相同并且root值相同

    bool isSameTree(TreeNode* p, TreeNode* q) {
        if(p==NULL)return q==NULL;
        else if(q==NULL)return false;
        else{
            return (isSameTree(p->left,q->left)&&isSameTree(p->right,q->right)&&p->val==q->val);
        }
        
    }

题解2 化简代码

    bool isSameTree(TreeNode* p, TreeNode* q) {
        if(!p&&!q)return true;
        if(!p||!q)return false;//有一个节点为空提前返回
            return (isSameTree(p->left,q->left)&&isSameTree(p->right,q->right)&&p->val==q->val);
    }

101. 对称二叉树

题目描述

【LeetCode】二叉树以及二叉树递归相关问题汇总_第5张图片

题解1 左子树反转后和右子树相同

class Solution {
public:
    TreeNode* reverse(TreeNode* root)//子树反转
    {
        if(root==NULL)return NULL;
        swap(root->left,root->right);
        reverse(root->left);
        reverse(root->right);
        return root;
    }
    bool issame(TreeNode* root1,TreeNode* root2)//判断是否相同
    {
        if(!root1&&!root2)return true;
        if(!root1||!root2)return false;
        return(issame(root1->left,root2->left)&&issame(root1->right,root2->right)&&root1->val==root2->val);
    }
    bool isSymmetric(TreeNode* root) {//反转后相同g
        if(root==NULL) return true;
        reverse(root->left);
        return(issame(root->left,root->right));
    }
};

题解2 右子树等于左子树 左子树等于右子树 根节点值相等

      bool dfs(TreeNode* root1,TreeNode* root2)
    {
        //if(!root1&&!root2)return true;
        if(!root1||!root2)return !root1&&!root2;
        return root1->val!=root2->val?false:dfs(root1->left,root2->right)&&dfs(root1->right,root2->left);
    }
    bool isSymmetric(TreeNode* root) {//反转后相同g
        //if(root==NULL) return true;
        return root?dfs(root->right,root->left):true;
    }

222. 完全二叉树的节点个数

题目描述

【LeetCode】二叉树以及二叉树递归相关问题汇总_第6张图片

题解1 计算每个节点的个数(没有用的完全二叉树的性质)

    int countNodes1(TreeNode* root) {
        //if()return 0;
        return root == NULL ? 0 : 1 + countNodes1(root->left) + countNodes1(root->right);
    }

题解2 计算二叉树的层数

    int countlevel(TreeNode* root)
    {
        int ret=0;
        while(root)
        {
            ret++;
            root=root->left;
        }
        return ret;
    }
    int countNodes2(TreeNode* root) {
        if(root==NULL)return 0;
        int llevel=countlevel(root->left);
        int rlevel=countlevel(root->right);
        if(llevel==rlevel)//如果有左子树和右子树 右子树的节点数+完全的左子树的节点
        {
            return countNodes2(root->right)+(1<<llevel);//位运算简化
        }
        return countNodes2(root->left)+countNodes2(root->right)+1;
    }

题解3 二分查找

    bool judge(TreeNode* node, int h){//计算高度
        while(node){
            h--;
            node = node->left;
        }
        return h == 0;
    }

    int countNodes(TreeNode* root) {
        if(NULL == root) return 0;
        TreeNode* node = root;
        int h = 0;//树的高度
        while(node){
            h++;
            node = node->left;
        }
        
        node   = root;
        int sum = 1 << (h - 1);//满节点的数量
        while((--h) > 0){
            TreeNode* right = node->right;
            if(judge(right, h))//判断右子树最大 如果和h相同
            {
                sum += 1 << (h - 1);//左子树是满的
                node = node->right;
            }else{//和h高度不同 
                node = node->left;//说明左子树不满
            }
        };
        return sum;
    }

110. 平衡二叉树

题目描述

【LeetCode】二叉树以及二叉树递归相关问题汇总_第7张图片

题解1

    int bfs(TreeNode* node)//-1表示不是平衡二叉树
    {
        if(node==NULL)return 0;
        int lbfs=bfs(node->left);
        if(lbfs==-1)return -1;//左右子树有一个不是 就提前终止
        int rbfs=bfs(node->right);
        if(rbfs==-1)return -1;
        
        return abs(lbfs-rbfs)<2? max(lbfs,rbfs)+1:-1;//看高度差

    }
    bool isBalanced(TreeNode* root) {
        return bfs(root)!=-1;
    }

题解2

     int countlevel(TreeNode* root)
    {
        if(root==NULL)return 0;
        return max(countlevel(root->left),countlevel(root->right))+1;
    }
    bool isBalanced(TreeNode* root) {
        if(root==NULL)return true;
        if(!isBalanced(root->left)||!isBalanced(root->right))return false;
        int llevel=countlevel(root->left);
        int rlevel=countlevel(root->right);
        return abs(llevel-rlevel)<2;
    }

题解3 优化 提前返回

    int countlevel(TreeNode* root)
    {
        if(root==NULL)return 0;
        return max(countlevel(root->left),countlevel(root->right))+1;
    }
    bool isBalanced(TreeNode* root) {//优化 提前返回
        if(root==NULL)return true;
        if(!(isBalanced(root->left)&&isBalanced(root->right)))return false;
        int llevel=countlevel(root->left);
        int rlevel=countlevel(root->right);
        return abs(llevel-rlevel)<2;
    }

注意递归的终止条件

112. 路径总和

题目描述

【LeetCode】二叉树以及二叉树递归相关问题汇总_第8张图片

题解 看左节点有没有sum-val的路径

    bool hasPathSum(TreeNode* root, int sum) {
        if(root==NULL)return sum==0;
        return hasPathSum(root->left,sum-root->val)||hasPathSum(root->right,sum-root->val);
    }

404. 左叶子之和

题目描述

【LeetCode】二叉树以及二叉树递归相关问题汇总_第9张图片

题解

如果是有左子树是左子叶 当前节点左子树值 +递归右子树
否则 左子叶的数量+右子叶的数量

    int sumOfLeftLeaves(TreeNode* root) {
        if(root==NULL)return 0;
        if(root->left&&root->left->left==NULL&&root->left->right==NULL)return sumOfLeftLeaves(root->right)+root->left->val;
        return sumOfLeftLeaves(root->left)+sumOfLeftLeaves(root->right);
    }

定义递归问题

257. 二叉树的所有路径

题目描述

【LeetCode】二叉树以及二叉树递归相关问题汇总_第10张图片

题解1 终止条件 必须是叶子节点

    vector<string> binaryTreePaths(TreeNode* root) {
        vector<string> ret;
        if(root==NULL) return ret;
        if(root->left==NULL&&root->right==NULL)//是叶子节点
        {
            ret.push_back(to_string(root->val));//结尾放当前节点
            return ret;
        }
        vector<string> lret=binaryTreePaths(root->left);//左子叶的路径
        for(int i=0;i<lret.size();i++)
        {
            ret.push_back(to_string(root->val)+"->"+lret[i]);
        }
        vector<string> rret=binaryTreePaths(root->right);//右子叶的路径
        for(int i=0;i<rret.size();i++)
        {
            ret.push_back(to_string(root->val)+"->"+rret[i]);
        }
        return ret;
    }

题解2

class Solution {
public:
    void dfs(TreeNode* root,vector<string>& ret)
    {
        if(root==NULL)return;
        if(root->left==NULL&&root->right==NULL)//是叶子节点
        {
            ret.back()+=to_string(root->val);
            return;
        }
        if(root->left&&root->right)//都有
        {
            string tmp=ret.back();//加入当前节点 再遍历左子树
            ret.back()+=to_string(root->val)+"->";
            dfs(root->left,ret);

            ret.push_back(tmp);//加上当前节点 遍历右子树
            ret.back()+=to_string(root->val)+"->";
            dfs(root->right,ret);
            return;
        }
        if(root->left)
        {
            ret.back()+=to_string(root->val)+"->";
            dfs(root->left,ret);
            return;
        }
        ret.back()+=to_string(root->val)+"->";
        dfs(root->right,ret);
        return;
    }
    vector<string> binaryTreePaths(TreeNode* root) {
        
        vector<string> ret;
        if(root==NULL)return ret;
        ret.push_back(string());//把结果传进来
        dfs(root,ret);
        return ret;
    }
};

题解3 使用栈

    vector<string> binaryTreePaths(TreeNode* root) {  
        vector<string> ret;
        if(root==NULL)return ret;
        stack<pair<TreeNode*,string>> s;//当前节点以及到当前节点的路径
        pair<TreeNode*,string> tmp;//临时变量
        s.push(make_pair(root,to_string(root->val)));
        while(!s.empty())
        {
            tmp=s.top();
            s.pop();
            if(tmp.first->right)//有右子树
            {
                s.push(make_pair(tmp.first->right,tmp.second+"->"+to_string(tmp.first->right->val)));//添加子树元素
            }
            if(tmp.first->left)//有左子树
            {
                s.push(make_pair(tmp.first->left,tmp.second+"->"+to_string(tmp.first->left->val)));//添加子叶元素
            }
            if(!tmp.first->right&&!tmp.first->left)//是叶子节点
            {
                ret.push_back(tmp.second);//在返回值添加
            }
        
        }
        return ret;
    }  

113. 路径总和 II

题目描述

【LeetCode】二叉树以及二叉树递归相关问题汇总_第11张图片

方法1 递归

public:
    void dfs(TreeNode* root,vector<vector<int>>&ret,vector<int>tmpret,int sum)
    {
        if(root==NULL)return;
        if(!root->left&&!root->right&&sum==root->val)//是子叶节点并且值相等
        {
            tmpret.push_back(root->val);
            ret.push_back(tmpret);//添加子路径
        }
        tmpret.push_back(root->val);//添加当前节点值
        dfs(root->left,ret,tmpret,sum-root->val);
        dfs(root->right,ret,tmpret,sum-root->val);
        return;
    }
    vector<vector<int>> pathSum(TreeNode* root, int sum) {
        vector<vector<int>>ret;
        vector<int> tmpret;
        dfs(root,ret,tmpret,sum);
        
        return ret;
    }

};

方法2 用栈模仿递归

   vector<vector<int>> res;
    vector<int> temp;//防止反复初始化数组 
    void dfs(TreeNode* root,int sum){
        int resum=sum-root->val;//要找的值
        temp.push_back(root->val);//假设它在
        if(resum==0&&!root->left&&!root->right)
			res.push_back(temp);//找到答案 
        if(root->left)
			dfs(root->left,resum);
        if(root->right)
			dfs(root->right,resum);
        temp.pop_back();//回溯  temp是全局变量
    }
    vector<vector<int>> pathSum(TreeNode* root, int sum) {
        if(root)dfs(root,sum);
        return res;
    }

129. 求根到叶子节点数字之和

题目描述

【LeetCode】二叉树以及二叉树递归相关问题汇总_第12张图片

题解

    int sum=0;//返回值
    int tmpsum=0;//临时的值
    int sumNumbers(TreeNode* root) {
        if(root==NULL) return 0;
        int t=tmpsum;//之前的累加
        tmpsum=tmpsum*10+root->val;//加上该节点
        if(!root->left&&!root->right)sum+=tmpsum;//叶子节点就在返回值上加
        sumNumbers(root->left);
        sumNumbers(root->right);
        tmpsum=t;
        return sum;
    }

复杂的二叉树递归问题

437. 路径总和 III

题目描述

【LeetCode】二叉树以及二叉树递归相关问题汇总_第13张图片

题解 分为包含当前节点和不包含当前节点 两种递归情况

    int pathSum(TreeNode* root, int sum) {
        if(root==NULL)return NULL;
        int ret=0;
        ret+=findpath(root,sum);
        ret+=pathSum(root->left,sum);
        ret+=pathSum(root->right,sum);
        return ret;
    }
    int findpath(TreeNode* root,int sum)//包含当前节点
    {
        if(root==NULL)return 0;
        int ret=0;
        if(root->val==sum)ret=1;
        ret+=(findpath(root->left,sum-root->val)+findpath(root->right,sum-root->val));//可能为负数
        return ret;
    }

你可能感兴趣的:(做题,二叉树)