算法训练Day17|二叉树part04(LeetCode 110.平衡二叉树、257.二叉树的所有路径、404.左叶子之和)

文章目录

  • 110.平衡二叉树
  • 257.二叉树的所有路径
  • 404.左叶子之和
    • 递归法
    • 迭代法


110.平衡二叉树

题目链接
给定一个二叉树,判断它是否是高度平衡的二叉树。
本题中,一棵高度平衡二叉树定义为:一个二叉树每个节点的左右两个子树的高度差的绝对值不超过1。

算法训练Day17|二叉树part04(LeetCode 110.平衡二叉树、257.二叉树的所有路径、404.左叶子之和)_第1张图片

根节点的高度就是这棵树的最大深度。
求深度可以从上到下去查 所以需要前序遍历(中左右),而高度只能从下到上去查,所以只能后序遍历(左右中)
这里看不懂可以看二叉树的最大深度和最小深度。

递归法的单层递归的逻辑:
(1)分别求左子树和右子树高度,计算高度差;
(2)如果高度差大于1,记当前树的高度为-1;否则,当前树的高度是max(左子树高度,右子树高度) + 1;
(3)当然,如果求出的左子树或右子树的高度已经为-1,直接返回-1即可(底层非平衡二叉树,结果会一直传给上层);
(4)最终返回整棵树高度是否为-1的bool值,即是否为平衡二叉树;

class Solution {
public:
    int gethight(TreeNode* root){
        if(root==nullptr) return 0;
        //nt result=-1;
        int leftdepth=gethight(root->left);
        if(leftdepth==-1) return -1;
        int rightdepth=gethight(root->right);
        if(rightdepth==-1) return -1;
        if(abs(leftdepth-rightdepth)>1) return -1;
        //else result=max(leftdepth,rightdepth)+1;
        else return 1+max(leftdepth,rightdepth);

    }
    bool isBalanced(TreeNode* root) {
        return gethight(root)==-1?false:true;
    }
};

257.二叉树的所有路径

题目链接
给定一个二叉树,返回所有从根节点到叶子节点的路径。
说明: 叶子节点是指没有子节点的节点。
算法训练Day17|二叉树part04(LeetCode 110.平衡二叉树、257.二叉树的所有路径、404.左叶子之和)_第2张图片

从根节点到叶子的路径,所以需要前序遍历,这样才方便让父节点指向孩子节点,找到对应的路径。

在这道题目中将第一次涉及到回溯,因为我们要把路径记录下来,需要回溯来回退一个路径再进入另一个路径。

算法训练Day17|二叉树part04(LeetCode 110.平衡二叉树、257.二叉树的所有路径、404.左叶子之和)_第3张图片
先使用递归的方式,来做前序遍历。要知道递归和回溯就是一家的,本题也需要回溯。

class Solution {
public:
    void getpath(TreeNode* cur,vector<int> &path,vector<string> &spath){
        path.push_back(cur->val);
        if(cur->left){
            getpath(cur->left,path,spath);
            path.pop_back();

        }
        if(cur->right){//可以控制空节点不入循环
            getpath(cur->right,path,spath);
            //递归完,要做回溯,因为path 不能一直加入节点,它还要删节点,然后才能加入新的节点。
            //回溯和递归是一一对应的,有一个递归,就要有一个回溯,所以回溯要和递归永远在一起,
            path.pop_back();
        }
        if(cur->left==nullptr&&cur->right==nullptr){// 左右孩子都为空,遇到叶子节点
            string str;
            for(int i=0;i<path.size()-1;i++){// 将path里记录的路径转为string格式
                str+=to_string(path[i]);
                str+="->";
            }
            str+=to_string(path[path.size()-1]);// 记录最后一个节点(叶子节点)
            spath.push_back(str);
        }
    }
    vector<string> binaryTreePaths(TreeNode* root) {
        vector<int> path;
        vector<string> spath;
        if(root==nullptr) return spath;
        getpath(root,path,spath);
        return spath;
    }
};

404.左叶子之和

题目链接
计算给定二叉树的所有左叶子之和。
算法训练Day17|二叉树part04(LeetCode 110.平衡二叉树、257.二叉树的所有路径、404.左叶子之和)_第4张图片

递归法

如果该节点的左节点不为空,该节点的左节点的左节点为空,该节点的左节点的右节点为空,则找到了一个左叶子。

因为要通过递归函数的返回值来累加求取左叶子数值之和,所以用后序遍历。

class Solution {
public:
    int sumOfLeftLeaves(TreeNode* root) {
        if (root == NULL) return 0;
        int leftValue = sumOfLeftLeaves(root->left);    // 左
        int rightValue = sumOfLeftLeaves(root->right);  // 右
        if (root->left && !root->left->left && !root->left->right) { // 左子树就是一个左叶子的情况
            leftValue = root->left->val;
        }
        int sum = leftValue + rightValue;               // 中
        return sum;
    }
};

迭代法

迭代法使用前中后序都是可以的,只要把所有节点都遍历到,把左叶子节点统计出来

class Solution {
public:
    int sumOfLeftLeaves(TreeNode* root) {
        stack<TreeNode*> st;
        if(root==nullptr) return 0;
        st.push(root);
        int result;
        while(!st.empty()){
            TreeNode* cur=st.top();
            st.pop();
            if(cur->left) st.push(cur->left);
            if(cur->right) st.push(cur->right);
            if(cur->left&&!cur->left->left&&!cur->left->right){
                result+=cur->left->val;
            }
        }
        return result;
    }
};

你可能感兴趣的:(算法与数据结构,算法,leetcode,c++,数据结构)