代码随想录第十三天:完全二叉树结点数、平衡二叉树、所有路径、左叶子之和

1.完全二叉树结点数

题目链接:. - 力扣(LeetCode)

讲解链接:代码随想录 (programmercarl.com)

视频链接:要理解普通二叉树和完全二叉树的区别! | LeetCode:222.完全二叉树节点的数量_哔哩哔哩_bilibili

本题可以当作普通树来数结点,遍历所有结点。

但是完全二叉树有自己的特点,首先满二叉树也是一颗完全二叉树,而满二叉树的结点可以通过公式计算。如果完全二叉树不是满的,那么它遍历的过程中一定有子树成为满二叉树。

因此每次递归可以先判断是否为满二叉树,而判断满二叉树的条件是,左右遍历深度相同。

递归法:

三要素

1.参数与返回值:需要统计结点个数,返回int类型。参数为树结点指针。

2.终止条件:遇到空指针终止。

3.单层逻辑:首先判断是否未满二叉树,若满则用公式计算并返回。若不满则再递归计算左右子树结点个数,返回左右子树结点和+1。

代码如下:

int count(TreeNode* root){
    if (root == nullptr)
        return 0;
    TreeNode* left = root->left;
    TreeNode* right = root->right;
    int leftDepth = 0;
    int rightDepth = 0;
    while (left != nullptr){
        left = left->left;
        leftDepth++;
    }
    while (right != nullptr){
        right = right->right;
        rightDepth++;
    }
    if (leftDepth == rightDepth)
        return (2 << leftDepth) - 1;
    int leftCount = count(root->left);
    int rightCount = count(root->right);
    return leftCount + rightCount + 1;
}

int countNodes(TreeNode* root) {
    return count(root);
}

2.平衡二叉树

题目链接:. - 力扣(LeetCode)

讲解链接:代码随想录 (programmercarl.com)

视频链接:后序遍历求高度,高度判断是否平衡 | LeetCode:110.平衡二叉树_哔哩哔哩_bilibili

平衡二叉树是左右子树高度差不超过1的二叉树。因此本题主要求解左右子树的高度。

递归法:

三要素

1.参数与返回值:需要比较左右子树高度,返回int类型。参数为树结点指针。

2.终止条件:空指针。

3.单层逻辑:先递归求左右子树高度,然后比较他们的绝对值之差。如果递归过程中某子树高度为-1(不平衡),就直接返回-1。如果平衡,该树的高度就是左右子树高度较大者+1。

代码如下:

int getHeight(TreeNode* root){
    if (root == nullptr)
        return 0;
    int leftHeight = getHeight(root->left);
    int rightHeight = getHeight(root->right);
    if (leftHeight == -1 || rightHeight == -1)
        return -1;
    if (abs(leftHeight - rightHeight) > 1)
        return -1;
    else
        return 1 + max(leftHeight, rightHeight);
}

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

3.所有路径

题目链接:. - 力扣(LeetCode)

讲解链接:代码随想录 (programmercarl.com)

视频链接:递归中带着回溯,你感受到了没?| LeetCode:257. 二叉树的所有路径_哔哩哔哩_bilibili

本题涉及回溯,因为我们要把路径记录下来,需要回溯来回退一个路径再进入另一个路径。

递归法:

三要素

1.参数与返回值:本题不需要返回值,路径与结果集从参数导入,还需要树结点指针作为参数。

2.终止条件:遇到叶子节点中止(路径走到头了),同时要将至今位置记录的path加入到结果集中。记录路径使用的是vector数组,而结果集的元素是string,因此需要将vector转换为string,然后再加入结果集。

3.单层逻辑:向左孩子结点前进,递归完后要回溯,将path中的元素pop()一个(即左孩子结点),因为接下来要想右孩子前进,同样递归完要进行回溯。

代码如下:

void traversal(TreeNode* cur, vector<int>& path, vector<string>& result){
    path.push_back(cur->val);
    if (cur != nullptr && cur->left == nullptr && cur->right == nullptr){
        string str;
        for (int i = 0; i < path.size() - 1; ++i) {
            str += to_string(path[i]);
            str += "->";
        }
        str += to_string(path[path.size() - 1]);
        result.push_back(str);
        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;
    traversal(root, path, result);
    return result;
}

4.左叶子之和

题目链接:. - 力扣(LeetCode)

讲解链接:代码随想录 (programmercarl.com)

视频链接:二叉树的题目中,总有一些规则让你找不到北 | LeetCode:404.左叶子之和_哔哩哔哩_bilibili

左叶子是作为左孩子的叶子节点。只看当前结点无法判断其是否为左叶子,需要从父节点开始判断。

递归法:

三要素

1.参数与返回值:需要返回子树左叶子之和,为int类型。参数为树节点指针。

2.结束条件:空指针或叶子节点(叶子节点没有孩子所有不会有下一个左叶子)。

3.单层逻辑:当遇到左叶子节点的时候,记录数值,然后通过递归求取左子树左叶子之和,和 右子树左叶子之和,相加便是整个树的左叶子之和。

代码如下:

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

tips:

if (root->left && !root->left->left && !root->left->right)
    leftSum = root->left->val;

这句代码是判断左孩子是否为左叶子。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值