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

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

时间:2024-02-15 23:45:03浏览次数:22  
标签:node right TreeNode val int 18 二叉树 左下角 left

找树左下角的值

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);
    }
};

标签:node,right,TreeNode,val,int,18,二叉树,左下角,left
From: https://www.cnblogs.com/tazdingo/p/18016758

相关文章

  • P1618 三连击(升级版)
    三连击(升级版)题目描述将\(1,2,\ldots,9\)共\(9\)个数分成三组,分别组成三个三位数,且使这三个三位数的比例是\(A:B:C\),试求出所有满足条件的三个三位数,若无解,输出No!!!。//感谢黄小U饮品完善题意输入格式三个数,\(A,B,C\)。输出格式若干行,每行\(3\)个数字。按照每行......
  • P1873 [COCI 2011/2012 #5] EKO / 砍树
    题目链接:一、本题为什么能想到利用二分解决?\(1.\)有单调性提高伐木机的高度,显然地,得到的木头会减少。同样地,放低得到的木头会增多。而正因为答案有单调性,所以我们可以使用二分。\(2.\)数据范围大如果采用暴力枚举,时间复杂度为\(O(n\cdotm)\)会超时。用二分优化后时间......
  • 二叉树
    二叉树「二叉树binarytree」是一种非线性数据结构,代表着祖先与后代之间的派生关系,体现着“一分为二”的分治逻辑。与链表类似,二叉树的基本单元是节点,每个节点包含:值、左子节点引用、右子节点引用。/*二叉树节点结构体*/typedefstructTreeNode{intval;//节点值int......
  • 二叉树遍历问题模板
    在二叉树遍历问题中,有三种常见的遍历方式:前序遍历、中序遍历和后序遍历。以下是这三种遍历方式的递归模板:1.前序遍历(PreorderTraversal):defpreorderTraversal(root):ifnotroot:return[]result=[]result.append(root.val)#处理当前节点......
  • 「杂题乱刷」洛谷 P1831
    题目链接一道简单数位dp题。多设一个支点和力矩和然后套板子就做完了。参考代码:点击查看代码/*Tips:你数组开小了吗?你MLE了吗?你觉得是贪心,是不是该想想dp?一个小时没调出来,是不是该考虑换题?*/#include<bits/stdc++.h>usingnamespacestd;#definemapunordered_m......
  • 24/02/14 [BJWC2018] 八维
    今天是情人节,而且今年是永夜抄正式版发行20周年(咏唱组20周年)。放一张我喜欢的咏唱:题目描述我们将一个\(M\)行\(N\)列的字符矩阵无限复制,可以得到一个无限字符矩阵。例如,对于以下矩阵:\[\begin{aligned}&\verb!honi!\\&\verb!hsin!\\\end{aligned}\]可以无限复......
  • 代码随想录算法训练营第十七天| 110.平衡二叉树 257. 二叉树的所有路径 404.左叶
    110.平衡二叉树 题目链接:110.平衡二叉树-力扣(LeetCode)思路:判断平衡二叉树,就是判断两个子树的高度差,继而问题转化为了如何求子树的高度——后序遍历(主要卡在了这里)。递归函数返回的是树的高度,同时用-1来表示退出递归(一开始想着用bool型作为返回值,发现函数不好设计)。同时要关......
  • P8667 [蓝桥杯 2018 省 B] 递增三元组
    二分计数#include<iostream>#include<stdio.h>#include<algorithm>#include<string>#defineFor(i,j,n)for(inti=j;i<=n;++i)usingnamespacestd;constintN=1e5+5;intn,arr[3][N],base[N];longlongans;int......
  • 863. 二叉树中所有距离为 K 的结点
    首先要将二叉树转换成图,再用bfs做。1,二叉树转换成图用哈希表存当前节点和与其相连的点;通过当前节点于其父节点实现遍历;点击查看代码unordered_map<TreeNode*,vector<TreeNode*>>graph;voidcreateGraph(TreeNode*node,TreeNode*parent){if(!node)......
  • 1339. 分裂二叉树的最大乘积
    这道题关键突破点就是先算出节点总和,然后找到一颗子树总和最接近总和的一半。乘积最大基本就是先要求总和,然后找到最接近总和一半。关键就是这一步,找到最适合子树的和。点击查看代码if(abs(2*cur-sum)<abs(2*best-sum)){best=cur;}完整代码:点击查看......