day15 | 110.平衡二叉树 257.二叉树的所有路径 404.左叶子之和

文章目录

    • 一、平衡二叉树
    • 二、[回溯小难]二叉树的所有路径
    • 三、左叶子之和

一、平衡二叉树

110.平衡二叉树
依旧是使用后序遍历来统计高度。

递归过程中,发现某节点的左右子树的高度差超过了1,我们就直接返回-1,不返回节点的高度了。

递归函数的参数和返回值:

int getHeight(TreeNode * node){}

终止条件:

if(node==nullptr) return 0;

单层递归逻辑:

如何判断以当前传入节点为根节点的二叉树是否是平衡二叉树呢?
当然是其左子树高度和其右子树高度的差值。分别求出其左右子树的高度,然后如果差值小于等于1,则返回当前二叉树的高度,否则返回-1,表示已经不是二叉平衡树了。

int leftHeight = getHeight(node->left);   // 左
if (leftHeight == -1)
    return -1;
int rightHeight = getHeight(node->right); // 右
if (rightHeight == -1)
    return -1;

int res;
if (abs(leftHeight - rightHeight) > 1)  // 根
    res = -1;
else
{
    res = 1 + max(leftHeight, rightHeight);
}
return res;

完整代码:

class Solution
{
public:
    int getHeight(TreeNode *node)
    {
        if (node == nullptr)
            return 0;

        int leftHeight = getHeight(node->left); // 左
        if (leftHeight == -1)
            return -1;
        int rightHeight = getHeight(node->right); // 右
        if (rightHeight == -1)
            return -1;

        int res;
        if (abs(leftHeight - rightHeight) > 1)  // 根
            res = -1;
        else
        {
            res = 1 + max(leftHeight, rightHeight);
        }
        return res;
    }
    bool isBalanced(TreeNode *root)
    {
        return getHeight(root) == -1 ? false : true;
    }
};

二、[回溯小难]二叉树的所有路径

257.二叉树的所有路径

我们这里要使用前序遍历。

递归函数的参数和返回值:

void travelsal(TreeNode *node){}

递归终止条件:

if (node->left == nullptr && node->right == nullptr)

单层递归逻辑:

// 单层递归处理逻辑
// 左
if (node->left)
{
    travelsal(node->left);
    path.pop_back(); // 为啥在这里pop_back()? 这是回溯的过程
}
// 右
if (node->right)
{
    travelsal(node->right);
    path.pop_back(); // 为啥在这里pop_back()? 这是回溯的过程
}
class Solution
{
private:
    vector<string> res;
    vector<int> path;
    void travelsal(TreeNode *node)
    {
        path.push_back(node->val); // 中 写在这里? 因为最后一个叶子节点也要加入到path中
        if (node->left == nullptr && node->right == nullptr)
        {
            string s;
            for (int i = 0; i < path.size() - 1; i++)
            {
                s += to_string(path[i]);
                s += "->";
            }
            s += to_string(path[path.size() - 1]); // 记录最后一个节点(叶子节点)
            res.push_back(s);
            return;
        }
        // 中 本该写在这里
		//path.push_back(node->val);
        
        // 单层递归处理逻辑
        // 左
        if (node->left)
        {
            travelsal(node->left);
            path.pop_back(); // 为啥在这里pop_back()? 这是回溯的过程
        }
        // 右
        if (node->right)
        {
            travelsal(node->right);
            path.pop_back(); // 为啥在这里pop_back()? 这是回溯的过程
        }
    }

public:
    vector<string> binaryTreePaths(TreeNode *root)
    {
        travelsal(root);
        return res;
    }
};

1、为啥用前序?
这样才方便让父节点指向孩子节点,找到对应的路径。

2、为什么会有回溯?
因为我们要用vector装数据,然后要把数据弹出去一部分,方便递归其他路径。

三、左叶子之和

404.左叶子之和

使用后续遍历最为简洁。
判断当前节点是不是左叶子是无法判断的,必须要通过节点的父节点来判断其左孩子是不是左叶子。
day15 | 110.平衡二叉树 257.二叉树的所有路径 404.左叶子之和_第1张图片
递归函数的参数和返回值:

int travelsal(TreeNode *node){}

终止条件:

 if (node == nullptr)
     return 0;

单层递归逻辑:

int leftnum = travelsal(node->left); // 左
if (node->left != nullptr && node->left->left == nullptr && node->left->right == nullptr)
    leftnum = node->left->val;
int rightnum = travelsal(node->right);// 右
int sum = leftnum + rightnum; // 中
return sum;

完整代码:

class Solution
{
public:
    int travelsal(TreeNode *node)
    {
        if (node == nullptr)
            return 0;

        int leftnum = travelsal(node->left);
        if (node->left != nullptr && node->left->left == nullptr && node->left->right == nullptr)
            leftnum = node->left->val;
        int rightnum = travelsal(node->right);
        int sum = leftnum + rightnum;
        return sum;
    }
    int sumOfLeftLeaves(TreeNode *root)
    {
        return travelsal(root);
    }
};

你可能感兴趣的:(笔试强训,二叉树)