代码随想录算法训练营第13天|二叉树part03

迭代法,大家可以直接过,二刷有精力的时候 再去掌握迭代法。感觉自己精力实在有限,还是暂时不考虑迭代法了。玛德,实在是过于难了。

110.平衡二叉树 (递归)

/**
 * 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 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;
    }
};

再一次涉及到,什么是高度,什么是深度,可以巩固一下。

现在发现,所谓的递归就是层层外包,领主的领主不是我的领主。我只给两个左右结点派活,最大深度多少。然后我再比较,给出结果。如果有一个已经不是平衡二叉树,那就没必要比较了。至于他们怎么解决,让他们自己再外包。确实挺好理解的。写代码的时候想 if (leftHeight == -1) return -1; if (rightHeight == -1) return -1;两行代码可不可以删了,因为我的思维是,如果不平衡二叉树,往上传递会一直不平衡。想了半天才意识到,不能删。因为虽然传递给上面会一直不平衡,但是如果两个都不平衡二叉树,一直往上比较,结果就平衡了。比如

        1
       / \
      2   2
     /     \
    3       3
   /         \
  4           4
错错得正了。所以还是得一有问题,直接打死。

题目链接/文章讲解/视频讲解:代码随想录

257. 二叉树的所有路径 (递归)

递归

  1. 递归函数参数以及返回值
  2. 确定递归终止条件
  3. 确定单层递归逻辑

这是大家第一次接触到回溯的过程, 我在视频里重点讲解了 本题为什么要有回溯,已经回溯的过程。

卧槽,只能说,确实本质上就是三个板斧,做了那么多回归。先把上面的图看一下就懂了一些,回溯我的第一感觉就是:“再探再报”,一直深入下去,找到一个,再找一个,再探再报。递归就很线性,附庸的附庸不是我的附庸。

如果对回溯 似懂非懂,没关系, 可以先有个印象。

/**
 * 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 {
    private:
    void traversal(TreeNode*cur,vector<int>&path,vector<string>&result)
    {
        path.push_back(cur->val);
        if(cur->left==nullptr&&cur->right==nullptr)
        {
            string sPath;
            for (int i = 0; i < path.size() - 1; i++) { // 将path里记录的路径转为string格式
                 sPath += to_string(path[i]);
                 sPath += "->";
              }   
        sPath += to_string(path[path.size() - 1]); // 记录最后一个节点(叶子节点)
        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(); // 回溯
        }
}
    
public:
    vector<string> binaryTreePaths(TreeNode* root) {
   vector<string>result;
   vector<int>path;
   if(root==nullptr)return result;
   traversal(root,path,result);
   return result;
    }
};

题目链接/文章讲解/视频讲解:代码随想录

404.左叶子之和 (递归)

其实本题有点文字游戏,搞清楚什么是左叶子,剩下的就是二叉树的基本操作。

其实这题感觉还挺不算难得,递归主要是传入什么,返回什么,中间运行什么。

题目链接/文章讲解/视频讲解:代码随想录

/**
 * 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 sumOfLeftLeaves(TreeNode* root) {
        if(root==nullptr)
        return 0; 
        int leftValue=0;
        if (root->left != NULL && root->left->left == NULL && root->left->right == NULL)
        leftValue=root->left->val;
        return leftValue+sumOfLeftLeaves(root->left)+sumOfLeftLeaves(root->right);
    }
};

222.完全二叉树的节点个数(递归)

纯递归法还是比较简单的,只要知道左边多少个,右边多少个,再加上自身就好了。

需要了解,普通二叉树 怎么求,完全二叉树又怎么求

/**
 * 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 {
private:
int getNodesNum(TreeNode* cur) {
        if (cur == NULL) return 0;
        int leftNum = getNodesNum(cur->left);      // 左
        int rightNum = getNodesNum(cur->right);    // 右
        int treeNum = leftNum + rightNum + 1;      // 中
        return treeNum;
    }
public:
    int countNodes(TreeNode* root) {
        return getNodesNum(root);
    }
};

题目链接/文章讲解/视频讲解:代码随想录

层序遍历感觉最好理解,对于来说最好使用,就很直观。

class Solution {
public:
    int countNodes(TreeNode* root) {
        queue<TreeNode*> que;
        if (root != NULL) que.push(root);
        int result = 0;
        while (!que.empty()) {
            int size = que.size();
            for (int i = 0; i < size; i++) {
                TreeNode* node = que.front();
                que.pop();
                result++;   // 记录节点数量
                if (node->left) que.push(node->left);
                if (node->right) que.push(node->right);
            }
        }
        return result;
    }
};

要记住完全二叉树长什么样,就是前面几层都填满了,就是完全二叉树。

然后就要利用完全二叉树的性质进行计算,满二叉树一定有子二叉树是完全二叉树

class Solution {
public:
    int countNodes(TreeNode* root) {
       
        if (root == nullptr) return 0;
        TreeNode* left = root->left;
        TreeNode* right = root->right;
        int leftDepth = 0, rightDepth = 0; // 这里初始为0是有目的的,为了下面求指数方便
        while (left) {  // 求左子树深度
            left = left->left;
            leftDepth++;
        }
        while (right) { // 求右子树深度
            right = right->right;
            rightDepth++;
        }
        if (leftDepth == rightDepth) {
            return (2 << leftDepth) - 1; // 注意(2<<1) 相当于2^2,所以leftDepth初始为0
        }
        return countNodes(root->left) + countNodes(root->right) + 1;
    }
};

还算是比较简单,主要是通过比较左子树和右子树,来判断子树是不是满二叉树。左子树结点加上右子树结点+1(本身)求出结果。

  • 16
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
代码随想录算法训练营是一个优质的学习和讨论平台,提供了丰富的算法训练内容和讨论交流机会。在训练营中,学员们可以通过观看视频讲解来学习算法知识,并根据讲解内容进行刷题练习。此外,训练营还提供了刷题建议,例如先看视频、了解自己所使用的编程语言、使用日志等方法来提高刷题效果和语言掌握程度。 训练营中的讨论内容非常丰富,涵盖了各种算法知识点和解题方法。例如,在第14训练营中,讲解了二叉树的理论基础、递归遍历、迭代遍历和统一遍历的内容。此外,在讨论中还分享了相关的博客文章和配图,帮助学员更好地理解和掌握二叉树的遍历方法。 训练营还提供了每日的讨论知识点,例如在第15的讨论中,介绍了层序遍历的方法和使用队列来模拟一层一层遍历的效果。在第16的讨论中,重点讨论了如何进行调试(debug)的方法,认为掌握调试技巧可以帮助学员更好地解决问题和写出正确的算法代码。 总之,代码随想录算法训练营是一个提供优质学习和讨论环境的平台,可以帮助学员系统地学习算法知识,并提供了丰富的讨论内容和刷题建议来提高算法编程能力。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [代码随想录算法训练营每日精华](https://blog.csdn.net/weixin_38556197/article/details/128462133)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值