(18/60)找树左下角的值、路径总和、从中序与后序遍历构造二叉树

找树左下角的值

leetcode:513. 找树左下角的值

层序迭代法

思路

层序遍历,每次更新result为每层最左侧元素。

复杂度分析

时间复杂度:遍历,O(N)。

空间复杂度:队列层序遍历,树*似完全二叉树时O(N),树极倾斜时O(logN)。

注意点

代码实现

/**
 * 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:
    // 层序迭代
    // 1. 最底层;2. 最左边
    int findBottomLeftValue(TreeNode* root) {
        queue<TreeNode*> que;
        if(!root->left && !root->right) return root->val;
        que.push(root);
        int result = 0;
        while(!que.empty()){
            int size = que.size();
            vector<int> vec;
            while(size--){
                TreeNode* node = que.front(); que.pop();
                vec.push_back(node->val);
                if(node->left) que.push(node->left);
                if(node->right) que.push(node->right);
            }
            result = vec[0];    // 每层遍历结束更新为最左边值
        }
        // 层序遍历结束,到达最底层
        return result;
    }
};

递归法

思路

递归遍历,如果深度比历史最深还深则更新返回值result

  1. 终止条件:是叶子节点。且如果深度大于历史最深则更新result
  2. 左右子树遍历。一定要先左后右!配合上面的深度严格大于历史最深更新,result每次更新为该层最左侧的元素。

复杂度分析

时间复杂度: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:
    // 递归法
    int result = INT32_MIN;
    int maxDepth = 0;
    void traversal(TreeNode* node,int depth){
        // 叶子节点返回
        if(!node->left && !node->right){    
            // 如果是新的一层则更新result
            if(depth > maxDepth){
                maxDepth = depth;
                result = node->val;
            }
        }
        if(node->left) traversal(node->left,depth + 1);
        if(node->right) traversal(node->right,depth + 1);
    }
    int findBottomLeftValue(TreeNode* root) {
        if(!root->left && !root->right) return root->val;
        else traversal(root,1);
        return result;
    }
};

路径总和

leetcode:

  1. 112. 路径总和
  2. 113. 路径总和 II

前序递归遍历法

思路

基于257. 二叉树的所有路径,遍历过程中,每次碰到叶子节点时进行结算比较,如果符合值,标志isFound = true,递归返回。

复杂度分析

时间复杂度:O(N)

空间复杂度:递归遍历,层数越多,递归越深,栈占用越多,*完全时O(logN),极倾斜时O(N)。

注意点

  1. 只在叶子节点时进行比较、结果的更新
  2. 可以不通过对比的方式,通过初始化count = targetSum,然后再递减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:
    // 递归找出所有的路径
    // 前序遍历
    bool isFound = false;
    void traversal(TreeNode* node,int pathSum,int targetSum){
        // 找到对应值终止
        if(isFound) return;
        pathSum += node->val;   // 中
        // 叶子节点也终止,且进行走完路径的结算比较!
        if(!node->left && !node->right){
            if(pathSum == targetSum) isFound = true;
            return;
        }
        if(node->left) traversal(node->left,pathSum,targetSum);
        if(node->right) traversal(node->right,pathSum,targetSum);
    }

    bool hasPathSum(TreeNode* root, int targetSum) {
        if(root == NULL) return false;
        else traversal(root,0,targetSum);
        return isFound;
    }
};

路经总和Ⅱ:

/**
 * 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:
    vector<vector<int>> result;
    void traversal(TreeNode* node,vector<int> path,int pathSum,int targetSum){
        path.push_back(node->val);
        pathSum += node->val;
        if(!node->left && !node->right){
            if(pathSum == targetSum) result.push_back(path);
            return;
        }

        if(node->left) traversal(node->left,path,pathSum,targetSum); 
        if(node->right) traversal(node->right,path,pathSum,targetSum);
    }
    vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
        vector<int> path;
        if(root == NULL) return result;
        traversal(root,path,0,targetSum);

        return result;
    }
};

从中序和后序遍历构造二叉树

leetcode:106. 从中序与后序遍历序列构造二叉树

递归法

思路

六脉神剑

  1. 如果数组为空,返回NULL;
  2. 取后序数组末元素为根节点的值;
  3. 找到根节点在中序数组位置的index
  4. 划分中序数组inLeftinRight
  5. 根据中序划分结果划分后序数组postLeftpostRight
  6. 递归构造左右节点。

复杂度分析

时间复杂度:O(NH)。每次递归都要遍历部分中序数组,总体完整遍历了中序数组。递归深度H取决于树的形态,若*衡则为O(NlogN),若不*衡则O(N^2)。

空间复杂度:O(N),递归栈的深度。但是由于每次递归都创建了新vector,占用空间比较多,时间也比较慢。

注意点

  1. rootTreeNode*类型,不能用TreeNode类型的构造函数。

    TreeNode* root = new TreeNode(postorder[postorder.size() - 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:
    TreeNode* traversal(vector<int>& inorder,vector<int>& postorder){
        // 第一步
        if(postorder.size() == 0) return NULL;
        // 第二步,取根节点
        TreeNode* root = new TreeNode(postorder[postorder.size() - 1]);
        // 第三步,找到根节点在中序数组的位置
        int i = 0;
        for(;i < inorder.size();i++){
            if(root->val == inorder[i]) break;
        }
        // 第四步,先划分中序
        // 左闭右开
        vector<int> inLeft(inorder.begin(),inorder.begin() + i);
        vector<int> inRight(inorder.begin() + i + 1,inorder.end()); 
        // 第五步,再划分后序
        vector<int> postLeft(postorder.begin(),postorder.begin() + inLeft.size());
        vector<int> postRight(postorder.begin() + inLeft.size(),postorder.end() - 1);
        // 第六步,递归构造左右节点
        root->left = traversal(inLeft,postLeft);
        root->right = traversal(inRight,postRight);

        return root;
    }
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        return traversal(inorder,postorder);
    }
};
posted @ 2024-02-15 23:25  Tazdingo  阅读(1567)  评论(0)    收藏  举报