(17/60)平衡二叉树、二叉树的所有路径、左叶子之和

年假后的第一天,感觉一切回到解放前T T

*衡二叉树

leetcode:110. *衡二叉树

后序递归求高度差法

思路

类似104. 二叉树的最大深度,求左右子树的最大深度(后序遍历求该点的最大高度,其实就等于该子树的最大深度

复杂度分析

时间复杂度:O(N)。

空间复杂度:**衡时树为O(logN),极倾斜时为O(N)。

注意点

  1. 返回值是1 + max(LHD,RHD)。(向上返回高度,从1开始)

代码实现

/**
 * 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 getHeightDiff(TreeNode* node){
        if(node == NULL) return 0;
        // 结果如果为-1则表示>1 继续向上返回-1
        int LHD = getHeightDiff(node->left);
        if(LHD == -1) return -1;
        int RHD = getHeightDiff(node->right);
        if(RHD == -1) return -1;
        int result = 0;
        if(abs(LHD - RHD) > 1) result = -1;
        else result = 1 + max(LHD,RHD);
        return result;
    }
    bool isBalanced(TreeNode* root) {
        return getHeightDiff(root) != -1 ? true : false;
    }
};

二叉树的所有路径

leetcode:257. 二叉树的所有路径

前序递归遍历

思路

首先要使用前序遍历,以利用递归调用(调用自身)的过程实现根->叶的指向。

个人理解:递归算法每层递归都包含递归调用(调用自身进入下一层递归)、递归回溯(触发返回条件,返回上层递归)两个部分,前序遍历在递归调用过程中进行处理(例如此题,自上而下遍历、层层深入时处理路径),后序遍历在递归回溯过程中进行处理(例如求最大深度,自底向上返回节点高度)。

  1. 先将当前节点放入path;
  2. 如果为叶节点,则将当前path加入结果数组中;
  3. 对左、右节点进行处理和path的回溯。(path.pop_back()

复杂度分析

时间复杂度:O(N)。

空间复杂度:二叉树递归遍历,**衡时O(logN),极倾斜时O(N)。

注意点

  1. to_string()函数

代码实现

回溯逻辑版:(对path的结果都被保存下来,回溯时应该回到原来状态,所以要补一句path.pop_back()

/**
 * 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 findPath(TreeNode* node,vector<int>& path,vector<string>& result){
        path.push_back(node->val);	// 中
        // 左右都为空,为叶子节点
        if(node->left == NULL && node->right == NULL){
            string spath;
            for(int i = 0;i < path.size() - 1; i++){
                spath += to_string(path[i]);
                spath += "->";
            }
            spath += to_string(path[path.size() - 1]);
            result.push_back(spath);
            return;
        }
        if(node->left){
            findPath(node->left,path,result);
            path.pop_back(); // 回溯
        }
        if(node->right){
            findPath(node->right,path,result);
            path.pop_back(); // 回溯
        }
    }

    vector<string> binaryTreePaths(TreeNode* root) {
        vector<int> path;
        vector<string> result;
        if(root == NULL) return result;
        else findPath(root,path,result);

        return result;
    }
};

精简版:(因为传入参数时没有对变量path进行修改,而是直接传入修改后的值,内层path加的"->"不会被保存下来;另外,由于没有用&引用,开头的+= to_string(node->val)也没有被保存,天然“回溯”)

/**
 * 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 traversal(TreeNode* node,string path,vector<string>& result){
        path += to_string(node->val);
        if(node->left == NULL && node->right == NULL){
            result.push_back(path);
            return;
        }
        if(node->left) traversal(node->left,path + "->",result);
        if(node->right) traversal(node->right,path + "->",result);
    }

    vector<string> binaryTreePaths(TreeNode* root) {
        vector<string> result;
        if(root == NULL) return result;
        else traversal(root,"",result);
        return result;
    }
};

返回左叶子之和

leetcode:404. 左叶子之和

递归遍历法

思路

遍历节点,如果节点满足1. 是叶节点;2. 是左节点,则sum+=node->val

本来打算说写后序自下而上返回sum,结果写成了前中后序都可以的。

复杂度分析

时间复杂度:O(N)。

空间复杂度:递归遍历二叉树,**衡时O(logN),极倾斜时O(N)。

注意点

代码实现

通用递归版:

/**
 * 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:
    // 遍历节点,如果节点是叶,且是左节点则加入sum,选择后序遍历。
    void traverseLeftSum(TreeNode* node,int index,int& sum){
        // index是左右子树标记,左子树为1,右子树为2,根为0
        if(node == NULL) return;
        if(node->left) traverseLeftSum(node->left,1,sum);
        if(node->right) traverseLeftSum(node->right,2,sum);
        if(node->left == NULL && node->right == NULL && index == 1){
            sum += node->val;
        }
    }
    int sumOfLeftLeaves(TreeNode* root) {
        int sum = 0;
        if(root->left == NULL && root->right == NULL)
            return 0;
        else traverseLeftSum(root,0,sum);
        return sum;
    }
};

后序遍历版通用版二:(想写后序遍历结果又是通用版)

/**
 * 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:
    // 遍历节点,如果节点是叶,且是左节点则加入sum,选择后序遍历。
    int traverseLeftSum(TreeNode* node,int index){
        // index是左右子树标记,左子树为1,右子树为2,根为0
        int sum = 0;	// 每一层的sum
        if(node == NULL) return 0; // 结束条件
        if(node->left) sum += traverseLeftSum(node->left,1);
        if(node->right) sum += traverseLeftSum(node->right,2);
        if(node->left == NULL && node->right == NULL && index == 1){
            sum += node->val;
        }
        return sum;
    }
    int sumOfLeftLeaves(TreeNode* root) {
        if(root->left == NULL && root->right == NULL)
            return 0;
        else return traverseLeftSum(root,0);
    }
};

后序遍历法:

/**
 * 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 == NULL) return 0;
        // 左子树是叶子情况的处理
        int leftVal = 0;
        if(root->left && !root->left->left && !root->left->right)
            leftVal = root->left->val;
        return leftVal + sumOfLeftLeaves(root->left) + sumOfLeftLeaves(root->right);
    }
};
posted @ 2024-02-14 23:49  Tazdingo  阅读(1630)  评论(0)    收藏  举报