代码随想录算法训练营第十五天| 222.完全二叉树的节点个数 110.平衡二叉树 257. 二叉树的所有路径 404.左叶子之和


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

题目链接:LeetCode 222.完全二叉树的节点个数

文章讲解:代码随想录
视频讲解:要理解普通二叉树和完全二叉树的区别! | LeetCode:222.完全二叉树节点的数量

思路:

 可以按照最基本的二叉树遍历结点来求结点数量,而本题给出的是完全二叉树,可以考虑完全二叉树的性质进行求解;

 一棵完全二叉树的填入顺序完全是按照层次遍历进行构建的;任意一个完全二叉树在结构上可以被分为若干个满二叉树的组合,如图:
在这里插入图片描述
 将当前结点下的若干满二叉树结点数量,加上上面的结点数量就是整个完全二叉树中的结点数量;

 判断满二叉树也很简单,分别向左向右遍历,如果深度一样,那么就是一棵满二叉树:
在这里插入图片描述

C++代码

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    int countNodes(TreeNode* root) {
        if(!root){
            return 0;
        }
        int leftd = 0, rightd = 0;
        TreeNode* left = root->left;
        TreeNode* right = root->right;
        while(left){
            leftd++;
            left = left->left;
        }
        while(right){
            rightd++;
            right = right->right;
        }
        if(leftd == rightd){
            return (2 << leftd)-1; //算术左移,代表2的left次幂
        }
        else{
            return countNodes(root->left)+countNodes(root->right)+1;
        }
    }
};

二、LeetCode 110.平衡二叉树

题目链接:LeetCode 110.平衡二叉树

文章讲解:代码随想录
视频讲解:后序遍历求高度,高度判断是否平衡 | LeetCode:110.平衡二叉树

思路

 本题的关键在于每个结点左右子树的最大高度;可以单独写一个递归函数求解最大高度,同时判断是否平衡,平衡的话返回子树最大高度+1, 否则返回 − 1 -1 1 代表不平衡了。

C++代码

class Solution {
public:
    // 返回以该节点为根节点的二叉树的高度,如果不是平衡二叉树了则返回-1
    int getHeight(TreeNode* node) {
        if (node == NULL) {
            return 0;
        }
        int leftHeight = getHeight(node->left);
        if (leftHeight == -1) return -1;
        int rightHeight = getHeight(node->right);
        if (rightHeight == -1) return -1;
        return abs(leftHeight - rightHeight) > 1 ? -1 : 1 + max(leftHeight, rightHeight);
    }
    bool isBalanced(TreeNode* root) {
        return getHeight(root) == -1 ? false : true;
    }
};

二、LeetCode 257. 二叉树的所有路径

题目链接:LeetCode 257. 二叉树的所有路径

文章讲解:代码随想录
视频讲解:递归中带着回溯,你感受到了没?| LeetCode:257. 二叉树的所有路径

思路

 本题遍历二叉树找出从根到叶子的路径,代码随想录给出的思路为,把二叉树当作解空间树,在解空间树中使用回溯算法输出正确答案;笔者对于回溯算法的学习将放在后续章节进行系统复习,因此此处只给出笔者自己的递归算法。

C++代码

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    void Path_search(TreeNode* node, vector<string>& paths, int i){
        TreeNode* subnode;
        string str;
        if(node->left) subnode = node->left;
        else if(node->right) subnode = node->right;
        else return; //遍历到叶子结点返回

        if(node->left && node->right){ //若左右孩子都存在,那么subnode一定是左孩子,因此处理右孩子即可
            paths.push_back(paths[i]);
            str = "->" + to_string(node->right->val);
            paths[paths.size()-1].append(str);
            Path_search(node->right, paths, paths.size()-1);
        }
        str = "->" + to_string(subnode->val);      
        paths[i].append(str);
        Path_search(subnode, paths, i);
    }
    
    vector<string> binaryTreePaths(TreeNode* root) {
        vector<string> paths(1, to_string(root->val));
        Path_search(root, paths, 0);
        return paths;
    }
};

 笔者的递归函数是处理当前结点的左右孩子,递归函数操作主体实际上改成处理当前结点会更方便一些

二、LeetCode 404.左叶子之和

题目链接:LeetCode 404.左叶子之和

文章讲解:代码随想录
视频讲解:二叉树的题目中,总有一些规则让你找不到北 | LeetCode:404.左叶子之和

思路

 要求返回二叉树中所有左叶子之和,设计递归函数传入参数为当前结点node与一个判断当前是否是左孩子的开关代数isleft,方便递归函数内的判断

C++代码

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    int ifLeftLeaf(TreeNode* node, bool isLeft){
        if(node){
            if(isLeft && !node->left && !node->right){ //若是叶子结点且是双亲的左孩子
                return node->val;
            }
            return ifLeftLeaf(node->left, true) + ifLeftLeaf(node->right, false); 
            //左为true,右为false
            //向左右子树中继续寻找
        }
        return 0;
    }
    int sumOfLeftLeaves(TreeNode* root) {
        return ifLeftLeaf(root, false);
    }
};


总结

 依然是对于二叉树遍历和递归函数的考察。之后在设计二叉树的递归函数时要注意尽可能在递归函数体内只操作当前结点,能一定程度上减小代码量,提高可读性。


文章图片来源:代码随想录 (https://programmercarl.com/)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值