代码随想录算法训练营第17天|110.平衡二叉树 ● 257. 二叉树的所有路径 ● 404.左叶子之和

110.平衡二叉树

为什么很多二叉树的题目都用后序遍历?因为左右中,可以把处理该节点放到最后,例如这题,只有得出了左右子树的高度,才能知道以该节点为根的子树是否为平衡二叉树。

思路:后序遍历,计算左右子树高度差,若有一颗子树不是平衡二叉树则直接返回-1(一颗子树不平衡,则整颗子树都不平衡),否则是平衡二叉树,返回左右子树最大的一个高度加上根节点的高度。

代码:

int gethight(TreeNode* node){
        if(node == nullptr) return 0;
        int lefthight = gethight(node->left);//左
        if(lefthight == -1) return -1;
        int righthight = gethight(node->right);//右
        if(righthight == -1) return -1;
        //中
        if(abs(lefthight-righthight)>1)//绝对值大于1不是平衡二叉树
            return -1;
        else
            return  1 + max(lefthight,righthight);//否则是平衡二叉树,返回以该节点为根的子树的最大高度
    }
    bool isBalanced(TreeNode* root) {
        return gethight(root) == -1 ? false:true;
    }

257.二叉树的所有路径

思路:为了记录路径,肯定是要用到回溯。遍历顺序用前序遍历,中左右。中则记录当前节点值,再往左和右递归。当遇到节点的左右孩子都为空,则该节点为叶子节点,此时就把path记录的路径转换成string类型加入结果。因为递归肯定有回溯,递归和回溯同时成对用。每调用一个traversal结束后就回溯一个节点(因为递归一直调用肯定是一条到叶子节点的路径)。

代码:

void traversal(TreeNode* cur,vector<int>& path,vector<string>& result){
        path.push_back(cur->val);//中,加入当前节点的值到路径中
        if(cur->left==nullptr && cur->right==nullptr){//若左右孩子都为空证明该节点是叶节点,记录完整路径
            string spath;//把path转换字符串spath再存回result
            for(int i = 0;i < path.size()-1;i++){
                spath += to_string(path[i]);
                spath += "->";
            }
            spath += to_string(path[path.size()-1]);//加入path的最后一个叶子节点,因为for循环中只加入了前面的是为了打印相应的->符号
            result.push_back(spath);
            return;
        }
        if(cur->left){//左
            traversal(cur->left,path,result);
            path.pop_back();//因为上面已经加入完路径了,之后回溯
        }
        if(cur->right){//左
            traversal(cur->right,path,result);
            path.pop_back();//因为上面已经加入完路径了,之后回溯
        }
    }
    vector<string> binaryTreePaths(TreeNode* root) {
        vector<string> result;
        vector<int> path;//记录路径
        if(root!=nullptr) traversal(root,path,result);
        return result;
    }

404.左叶子之和

思路:判断是否为叶子节点判断有没有左右孩子,判断是不是左节点需要在父节点才可以进行判断。遍历用后序遍历,左右中,先收集左子树左叶子之和,再收集右子树左叶子之和.最后中则把左子树和右子树左叶子之和相加。

代码:

int sumOfLeftLeaves(TreeNode* root) {
        if(root == nullptr) return 0;
        if(root->left==nullptr && root->right==nullptr) return 0;
        //这层不加不行,会让递归多进行一次,会在上一个root==null返回,如果加了会在其叶子节点返回,所以会返回其叶子节点的父节点

        int leftValue = sumOfLeftLeaves(root->left);//左
        //左孩子节点不为空且其左孩子节点是叶子节点则为左叶子
        if(root->left!=nullptr && root->left->left==nullptr && root->left->right==nullptr){
            leftValue = root->left->val;
        }
        int rightValue = sumOfLeftLeaves(root->right);//右
        int sum = leftValue + rightValue;//中,统计左子树的左叶子总和和右子树的左叶子总和
        return sum;
    }

  • 23
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值