算法学习打卡day17|110.平衡二叉树、257. 二叉树的所有路径、404.左叶子之和

75 阅读4分钟

110.平衡二叉树

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

示例 1: 输入:root = [3,9,20,null,null,15,7] 输出:true

思路:

  • 先明白一个概念,什么是二叉树高度和深度?
    • 二叉树节点的深度:指从根节点到该节点的最长简单路径边的条数。
    • 二叉树节点的高度:指从该节点到叶子节点的最长简单路径边的条数。
    • 另外,一般求高度用后序遍历,而求深度用前序遍历。 在这里插入图片描述
  • 递归法:判断左右子树的高度,然后求其差值,只要大于1,就不是平衡二叉树,小于1就返回其最大高度。
  • 递归三部曲
    • 确定函数参数和返回值:参数就是根节点、返回值是树的最大高度,当然一旦知道不是平衡二叉树可以返回-1,标记。
    • 确定退出条件,if (root == nullptr) return 0;
    • 单步处理逻辑,先判断左右子树返回值是不是-1,不是的话比较两子树高度之差,大于1返回-1,否则返回树的最大高度。

代码实现:

int get_high(TreeNode* root) {
        if (root == nullptr)    return 0;

        int left_high = get_high(root->left);
        if (left_high == - 1)   return -1;
        int right_high = get_high(root->right);
        if (right_high == -1)   return - 1;
        if (abs(left_high - right_high) > 1) {
            return -1;
        }
        return max(left_high, right_high) + 1;
    }
    bool isBalanced(TreeNode* root) {
        if (root == nullptr) return true;
        return get_high(root) == -1 ? false : true;
    }
  • 迭代法(比较繁琐,有思路就行):迭代法比较复杂,先写一个函数求左右子树的高度(后序遍历),然后遍历(哪种遍历方式都可以)二叉树节点判断每个节点是不是平衡二叉树。

257. 二叉树的所有路径

力扣题目链接 题目描述: 给你一个二叉树的根节点 root ,按 任意顺序 ,返回所有从根节点到叶子节点的路径。 叶子节点 是指没有子节点的节点。

思路:

  • 递归法:因为是根节点到所有叶子节点,那么可以采用前序遍历,递归三部曲,如下:
    • 确定函数参数和返回值:函数参数首先是根节点、然后还需要一个results存储结果集,另外还需要一个数组或string来存储路径。由于我们没必要处理返回值,返回值为void。
    • 函数退出条件:在碰到叶子节点时,说明形成一条完整的路径,直接放到results里退出即可。
    • 单步处理逻辑:左右子节点非空时,分别递归左右子节点即可。
void traversal(TreeNode* root, string path, vector<string>& results) {
        path += to_string(root->val);
        if (!root->right && !root->left) {
            results.push_back(path);
        }
        if(root->right) {
            traversal(root->right, path + "->", results);
        }
        if(root->left) {
            traversal(root->left, path + "->", results);
        }
    }
    vector<string> binaryTreePaths(TreeNode* root) {
        if(root == nullptr) {
            return {};
        }
        string path;
        vector<string> results;
        traversal(root, path, results);
        return results;
    }
  • 迭代法:
    • 利用两个栈,一个栈用来处理(存路径),一个栈用来访问(存节点),同样采用前序遍历实现。碰到叶子节点就将路径存到结果集。

代码实现

vector<string> binaryTreePaths(TreeNode* root) {
        if(root == nullptr) {
            return {};
        }
        stack<TreeNode*> stk;
        stk.push(root);
        stack<string> stk1;
        stk1.push(to_string(root->val));
        vector<string> results;
        while(!stk.empty()) {
            TreeNode* cur = stk.top();
            string path = stk1.top();
            stk.pop(), stk1.pop();
            if (!cur->left && !cur->right) {
                results.push_back(path);
            }
            if (cur->left) {
                stk.push(cur->left);
                stk1.push(path + "->" + to_string(cur->left->val));
            }
            if (cur->right) {
                stk.push(cur->right);
                stk1.push(path + "->" + to_string(cur->right->val));
            }
        }
        return results;
    }

404.左叶子之和(这道题通过父节点判断子节点,和其他题有点差别)

力扣题目链接 题目描述: 给定二叉树的根节点 root ,返回所有左叶子之和。

思路:

  • 因为要找左叶子节点,首先这个节点得是叶子节点(左右子树都为空),其次我们无法判断是左叶子还是右叶子,那么只能通过父节点来判断,明白这个就好做了。
  • 递归法:本体递归逻辑就是后序遍历,找出左子树的左叶子之和,和右子树的左叶子之和,相加即可,然后通过父节点来找左叶子节点,那么直接上递归三部曲:
    • 确定函数参数和返回值:参数为根节点,,返回值为sum
    • 确定函数退出条件:当节点为空时,返回0(把左节点非空和右节点非空加到单步逻辑里,这个判断条件就可以不写了)
    • 确定单步处理逻辑:当左节点不为空时,判断左节点是不是叶子节点,是的话加到left_sum,不是的话,递归左右节点,最后返回return left_sum + right_sum;

代码实现:

int sumOfLeftLeaves(TreeNode* root) {
        if (root == nullptr)    return 0;
        int left_sum = 0, right_sum = 0;
        if (root->left && !root->left->left && !root->left->right) {
            left_sum = root->left->val;
        } else {
            left_sum = sumOfLeftLeaves(root->left);
        }
        right_sum = sumOfLeftLeaves(root->right);
        return left_sum + right_sum;
    }
  • 迭代法:直接前后序遍历或者层次遍历找每个节点的左叶子节点即可
//前序遍历
int sumOfLeftLeaves(TreeNode* root) {
        if (root == nullptr)    return 0;
        stack<TreeNode*> stk;
        stk.push(root);
        int sum = 0;
        while(!stk.empty()) {
            TreeNode* cur = stk.top();
            stk.pop();
            if (cur->left && !cur->left->left && !cur->left->right) {
                sum += cur->left->val;
            }
            if (cur->left)  stk.push(cur->left);
            if (cur->right) stk.push(cur->right);
        }
        return sum;
    }