二叉树OJ实战

目录

二叉树某一节点X祖先节点的交集(证明题)

LeetCode_100. 相同的树

LeetCode_965. 单值二叉树

LeetCode_101. 对称二叉树

LeetCode_226. 翻转二叉树

LeetCode_112. 路径总和

LeetCode_113. 路径总和 II

LeetCode_110. 平衡二叉树

LeetCode_98. 验证二叉搜索树

二叉树中最大的二叉搜索子树的大小

LeetCode_105. 从前序与中序遍历序列构造二叉树

总结


二叉树某一节点X祖先节点的交集(证明题)

题目描述:

对于某个二叉树,X是二叉树中某一个节点,得到了整棵树的先序遍历,也知道这颗树的后序遍历。

则有结论:先序遍历X之前的节点定义为集合A,后序遍历X之后的节点定义为集合B,,则 A∩B得到的集合就是X的祖先节点集合  

思路分析:

二叉树的前序遍历的顺序为:当前节点->左子树->右子树,而后续遍历的顺序为:左子树->右子树->当前节点。所以对于某个节点X,其所有的祖先节点一定在先序序列的前面,一定在后续序列的后面。所以A∩B得到的集合就是X的祖先节点集合

LeetCode_100. 相同的树

题目描述:

给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。

如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。

示例 1:


输入:p = [1,2,3], q = [1,2,3]
输出:true


示例 2:


输入:p = [1,2], q = [1,null,2]
输出:false


示例 3:


输入:p = [1,2,1], q = [1,1,2]
输出:false

提示:

两棵树上的节点数目都在范围 [0, 100] 内
-104 <= Node.val <= 104

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/same-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路分析:

这题思路很简单,就是两棵树从根开始对比,如果根节点相等,就接着判断左子树是否相等,然后接着判断右子树是否相等。

仔细看,这里的思路就是前序遍历的思路,都是先处理当前节点,然后左子树,右子树。

我的题解:

/**
 * 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 isSameTree(TreeNode* p, TreeNode* q) 
    {
        //base case
        if(p == nullptr && q == nullptr)
            return true;
        else if(p == nullptr || q == nullptr)
            return false;
        
        //normal case
        if(p->val ==  q->val)
            return isSameTree(p->left, q->left) && isSameTree(p->right, q->right);
        return false;  
    }
};

LeetCode_965. 单值二叉树

题目描述:

如果二叉树每个节点都具有相同的值,那么该二叉树就是单值二叉树。

只有给定的树是单值二叉树时,才返回 true;否则返回 false。

示例 1:

输入:[1,1,1,1,1,null,1]
输出:true


示例 2:

输入:[2,2,2,5,2]
输出:false
 

提示:

给定树的节点数范围是 [1, 100]。
每个节点的值都是整数,范围为 [0, 99] 。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/univalued-binary-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路分析:

由于条件是绝对的所有节点的数值相等,所以就以根节点为基准进行判断。按照左子树,右子树的顺序判断。需要注意控制空节点的边界条件。

我的题解:

/**
 * 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 isUnivalTree(TreeNode* root) 
    {
        if(root == nullptr)
            return true;
        int val = root->val;
        //左右子树为空的情况就直接默认符合条件
        int left = root->left == nullptr ? val : root->left->val; 
        int right = root->right == nullptr ? val : root->right->val; 
        if(left == val && right == val)
            return isUnivalTree(root->left) && isUnivalTree(root->right);
        return false;  
        
    }
};

LeetCode_101. 对称二叉树

题目描述:

给你一个二叉树的根节点 root , 检查它是否轴对称。

示例 1:


输入:root = [1,2,2,3,4,4,3]
输出:true


示例 2:


输入:root = [1,2,2,null,3,null,3]
输出:false

提示:

树中节点数目在范围 [1, 1000] 内
-100 <= Node.val <= 100

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/symmetric-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路分析:

由于是判断对称,所以直接不用管根节点,先判断左右子树是否相等,然后进一步判断左子树的右子树是否等于右子树的左子树,并且右子树的右子树是否等于左子树的左子树。

上述过程大致也可以分成是前序遍历,先判断根的左右节点树是否是对称的,然后判断左子树是否对称,接着判断右子树去是否对称。先操作根节点,然后左子树,右子树。

/**
 * 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 judge(TreeNode* l, TreeNode* r)
    {
        //base case
        if(l == nullptr && r == nullptr)
            return true;
        else if(l == nullptr || r == nullptr)
            return false;
        //normal case
        if(l->val == r->val)
            return judge(l->left, r->right) && judge(l->right, r->left);
        return false;
    }
    bool isSymmetric(TreeNode* root) 
    {
        return judge(root->left, root->right);

    }
};

LeetCode_226. 翻转二叉树

题目描述:

给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。

示例 1:

输入:root = [4,2,7,1,3,6,9]
输出:[4,7,2,9,6,3,1]


示例 2:

输入:root = [2,1,3]
输出:[2,3,1]


示例 3:

输入:root = []
输出:[]
 

提示:

树中节点数目范围在 [0, 100] 内
-100 <= Node.val <= 100

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/invert-binary-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路分析:

这题和对称二叉树有些相似之处,大体思路就是将左右子树交换。这里我们从叶子节点开始,将两个同一父母的叶子节点交换,从下往上。

这就是后续遍历的做法(这题用前序遍历也能做)

我的题解:

/**
 * 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* invertTree(TreeNode* root) 
    {
        /*先反转左右子树,再反转当前节点*/
        //base case
        if(root == nullptr)
            return nullptr;
        //normal case
        invertTree(root->left);
        invertTree(root->right); 
        TreeNode* left = root->left;
        TreeNode* right = root->right;
        root->left = right;
        root->right = left;
        return root;
    }
};

LeetCode_112. 路径总和

题目描述:

给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true ;否则,返回 false 。

叶子节点 是指没有子节点的节点。

示例 1:


输入:root = [5,4,8,11,null,13,4,7,2,null,null,null,1], targetSum = 22
输出:true
解释:等于目标和的根节点到叶节点路径如上图所示。


示例 2:


输入:root = [1,2,3], targetSum = 5
输出:false
解释:树中存在两条根节点到叶子节点的路径:
(1 --> 2): 和为 3
(1 --> 3): 和为 4
不存在 sum = 5 的根节点到叶子节点的路径。


示例 3:

输入:root = [], targetSum = 0
输出:false
解释:由于树是空的,所以不存在根节点到叶子节点的路径。
 

提示:

树中节点的数目在范围 [0, 5000] 内
-1000 <= Node.val <= 1000
-1000 <= targetSum <= 1000

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/path-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路分析:

这题的一个核心思路就是:设置一个sum用于保存当前路径的和,当走到叶子节点且符合条件时就返回true,当走完整棵树的时候就说明没有符合条件的路径和,返回false。

注意:只有走到根节点的时候才能判断要返回true,还是继续,还是退出。即使某一个中间分支节点的路径和已经符合条件了也不行,必须是叶子节点才可以。

我的题解:

/**
 * 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 _hasPathSum(TreeNode* root, int curSum, int targetSum)
    {
        //base case
        curSum += root->val;                 
        if(root->left == nullptr && root->right == nullptr)
            return curSum == targetSum;
        //noremal case
        bool left = false, right = false;
        if(root->left != nullptr)
            left = _hasPathSum(root->left, curSum, targetSum);
        if(root->right != nullptr)
            right = _hasPathSum(root->right, curSum, targetSum);
        return left || right;
    }
    bool hasPathSum(TreeNode* root, int targetSum) 
    {
        //base case
        if(root == nullptr)
            return false;
        //normal case
        return _hasPathSum(root, 0, targetSum);
    }
};

LeetCode_113. 路径总和 II

题目描述:

给你二叉树的根节点 root 和一个整数目标和 targetSum ,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。

叶子节点 是指没有子节点的节点。

示例 1:


输入:root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22
输出:[[5,4,11,2],[5,8,4,5]]


示例 2:


输入:root = [1,2,3], targetSum = 5
输出:[]


示例 3: 

输入:root = [1,2], targetSum = 0
输出:[]
 

提示:

树中节点总数在范围 [0, 5000] 内
-1000 <= Node.val <= 1000
-1000 <= targetSum <= 1000

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/path-sum-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路分析:

这题其实就是在上一题的基础上改版。我们只需要针对性的修改即可。

但值得注意的是,对于path数组何时push_back进来,何时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 {
private:

public:
    void pathSumCreate(TreeNode* root,vector<int>& curPath, int curSum, int targetSum, vector<vector<int>>& Path)
    {
        //base case
        curPath.push_back(root->val);
        curSum += root->val;
        if(root->left == nullptr && root->right == nullptr && curSum == targetSum)
        {
            Path.push_back(curPath);
            curSum -= root->val;
        }
        if(root->left != nullptr)
        {
            pathSumCreate(root->left, curPath, curSum, targetSum, Path);     
            curPath.pop_back();
        }
        if(root->right != nullptr)
        {
            pathSumCreate(root->right, curPath, curSum, targetSum, Path);     
            curPath.pop_back();
        }
    }
    vector<vector<int>> pathSum(TreeNode* root, int targetSum) 
    {
        vector<vector<int>> Path;
        vector<int> curPath;
        if(root == nullptr)
            return Path;
        pathSumCreate(root, curPath, 0, targetSum, Path);
        return Path;
    }
};

LeetCode_110. 平衡二叉树

题目描述:

给定一个二叉树,判断它是否是高度平衡的二叉树。

本题中,一棵高度平衡二叉树定义为:

一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。

示例 1:


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


示例 2:


输入:root = [1,2,2,3,3,null,null,4,4]
输出:false


示例 3:

输入:root = []
输出:true
 

提示:

树中的节点数在范围 [0, 5000] 内
-104 <= Node.val <= 104

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/balanced-binary-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路分析:

一个很常规的思路就是获得两个子树的高度,判断是否合法,接着走到两个子树的位置,再判断。但这样有一个很大的开销就是获取子树的高度。

所以我们可以把获取树的高度的代码稍加修改,将判断平衡的过程融入进去。

这里我们就发现:如果一个题目需要用到一些信息,那么我们可以尝试着写一个获取信息的代码,然后将题目的具体要求融入到这个代码中,进而达到一个高效的目的。但这只适用于像这题这种只需要一个或者很少信息的情况。

我的题解:

/**
 * 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 subHight(TreeNode* root)
    {
        //base case
        if(root == nullptr)
            return true;
        
        //
        int left = subHight(root->left);
        int right = subHight(root->right);
        if(left == -1 || right == -1 || abs(left - right) > 1)
            return -1;
        return max(left, right) + 1; //返回高度
    }
    bool isBalanced(TreeNode* root) 
    {
        return subHight(root) > 0;
    }
};

LeetCode_98. 验证二叉搜索树

题目描述:

给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。

有效 二叉搜索树定义如下:

节点的左子树只包含 小于 当前节点的数。
节点的右子树只包含 大于 当前节点的数。
所有左子树和右子树自身必须也是二叉搜索树。
 

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/validate-binary-search-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路分析:

这题我们介绍两种做法。

做法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 
{
private:
    long long preVal = LLONG_MIN; //初始化为最小值
public:
    bool isValidBST(TreeNode* root) 
    {
        //base case
        if(root == nullptr)
            return true;
        //中序遍历
        /*左*/
        if(!isValidBST(root->left))
            return false;
        /*中*/
        if(root->val <= preVal)
            return false;
        preVal = root->val;
        /*右*/     
        return isValidBST(root->right);
    }
};

做法2:树型DP

树型DP这里要介绍一下,树型DP的通用模板就是:根据题目的要求分析出所需要的信息info,然后通过一个process过程对树进行操作,最终头节点的info就是我们想要的。

比如这题,我们是通过左边最大小于当前节点,右边最小大于当前节点,并且左右子树都是二叉查找树来判断的,所以我们分析出所需要的信息就是以当前节点为根的最大值,最小值,和是否为二叉查找树。接下来我们就是利用这些信息解决问题了。

代码实现如下:

/**
 * 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 isValidBST(TreeNode* root) 
    {
        return process(root)->isBST;
    }
    struct info
    {
        bool isBST;
        int max;
        int min;

        info (bool _is, int _max, int _min) : isBST(_is), max(_max), min(_min) {}
        
    };
    info* process(TreeNode* root)
    {
        if(root == nullptr)
            return nullptr;
        info* left = process(root->left);
        info* right = process(root->right);

        bool is = true;
        int cur_max = root->val, cur_min = root->val;

        if(left != nullptr)
        {
            cur_max = std::max(cur_max, left->max);
            cur_min = std::min(cur_min, left->min);
            is = is && left->isBST && root->val > left->max;
        }
        if(right != nullptr)
        {
            cur_max = std::max(cur_max, right->max);
            cur_min = std::min(cur_min, right->min);
            is = is && right->isBST && root->val < right->min;
        }

        return new info(is, cur_max, cur_min);
    }
};

二叉树中最大的二叉搜索子树的大小

题目描述:

链接:找到二叉树中的最大搜索二叉子树__牛客网
来源:牛客网
 

给定一颗二叉树,已知其中所有节点的值都不一样,找到含有节点最多的搜索二叉子树,输出该子树总节点的数量。

搜索二叉树是指对于二叉树的任何一个节点,都大于其左子树中的全部节点,但是小于其右子树中的全部节点。

 

输入描述:

第一行输入两个整数 n 和 root,n 表示二叉树的总节点个数,root 表示二叉树的根节点。

以下 n 行每行三个整数 fa,lch,rch,表示 fa 的左儿子为 lch,右儿子为 rch。(如果 lch 为 0 则表示 fa 没有左儿子,rch同理)

ps:节点的编号就是节点的值。

注意:子树必须包含其所有后代。

题目分析:

这题还是使用树型DP的方法比较好做。先分析,想要知道最大二叉查找树的大小,可以分为两种情况:最大二叉查找树包括根节点的情况,最大二叉查找树不包括根节点的情况。而这两种情况的判断就需要左右子树是否是二叉查找树,左右子树节点的个数,左右子树最大二叉查找树的节点个数,左右子树的最大、最小值这5个信息,我们发现如果最大二叉查找树的节点个数恰好等于节点个数的话,那么此时这颗子树就是二叉查找树,所以我们设置info的时候就可以少维护一个信息,只需要写4个信息即可。

具体的代码实现如下:

#include <iostream>
using namespace std;

struct node
{
	int val;
	node* left;
	node* right;
	node() :val(0), left(nullptr), right(nullptr) {}
	node(int _val) :val(_val), left(nullptr), right(nullptr) {}
};

class solution
{
private:
	node* buyTree()
	{
		int val, l_val, r_val;
		cin >> val >> l_val >> r_val;
		node* root = new node(val);
		if (l_val) root->left = buyTree();
		if (r_val) root->right = buyTree();
		return root;
	}

	struct info
	{
		int max;
		int min;
		int maxBSTsize;
		int nodeSize;
		info(int _max, int _min, int _maxBST, int _nodeSize) :
			max(_max), min(_min), maxBSTsize(_maxBST), nodeSize(_nodeSize) {}
	};

	info* process(node* root)
	{
		if (root == nullptr)
			return nullptr;
		info* left = process(root->left);
		info* right = process(root->right);

		int cur_max = root->val, cur_min = root->val, node_size = 1;
		int p1 = -1, p2 = -1, p3 = -1;
		bool is_left = true, is_right = true;


		if (left != nullptr)
		{
			cur_max = std::max(cur_max, left->max);
			cur_min = std::min(cur_min, left->min);
			node_size += left->nodeSize;
			p1 = left->maxBSTsize;
			is_left = left->maxBSTsize == left->nodeSize && root->val > left->max;
		}

		if (right != nullptr)
		{
			cur_max = std::max(cur_max, right->max);
			cur_min = std::min(cur_min, right->min);
			node_size += right->nodeSize;
			p2 = right->maxBSTsize;
			is_right = right->maxBSTsize == right->nodeSize && root->val < right->min;
		}

		if (is_left && is_right)
			p3 = (!left ? 0 : left->nodeSize) + (!right ? 0 : right->nodeSize) + 1;
		int maxBST = std::max(std::max(p1, p2), p3);
		return new info(cur_max, cur_min, maxBST, node_size);
	}

public:
	int getMaxBSTsize()
	{
		//创建树
		int n, val;
		cin >> n >> val; //用不到
		node* tree = buyTree();
		return process(tree)->maxBSTsize;
	}
};

int main()
{
	cout << solution().getMaxBSTsize() << endl;
	return 0;
}


LeetCode_105. 从前序与中序遍历序列构造二叉树

题目描述:

给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。

示例 1:


输入: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
输出: [3,9,20,null,null,15,7]


示例 2:

输入: preorder = [-1], inorder = [-1]
输出: [-1]
 

提示:

1 <= preorder.length <= 3000
inorder.length == preorder.length
-3000 <= preorder[i], inorder[i] <= 3000
preorder 和 inorder 均 无重复 元素
inorder 均出现在 preorder
preorder 保证 为二叉树的前序遍历序列
inorder 保证 为二叉树的中序遍历序列

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/construct-binary-tree-from-preorder-and-inorder-traversal
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路分析:

这题就是模拟,没什么特别的。

我的题解:

/**
 * 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:
    unordered_map<int,int> indexMap; //key - index
public:
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) 
    {
        int size = preorder.size();
        TreeNode* newTree = nullptr;
        for(int i = 0; i < size; i++)
        {
            indexMap[inorder[i]] = i;
        }   
        return _buildTree(preorder, 0, size - 1, inorder, 0, size - 1);

    }
private:
    TreeNode* _buildTree(vector<int>& preorder, int pre_left, int pre_right, vector<int>& inorder, int in_left, int in_right) 
    { 
        if(pre_right < pre_left || in_right < in_left)
            return nullptr;

        TreeNode* newNode = new TreeNode(preorder[pre_left]);

        /*这里写的太乱了,要改一下*/
        int in_root = indexMap[preorder[pre_left]];
        int left_num = in_root  - in_left, right_num = in_right - in_root;
        newNode->left = _buildTree(preorder, pre_left + 1, pre_left + left_num, inorder, in_left, in_root - 1);
        newNode->right = _buildTree(preorder, pre_right - right_num + 1, pre_right, inorder, in_root + 1, in_right);

        return newNode;
    } 
}; 

总结

做二叉树的题常规思路就是:前序、中序、后续遍历,层序遍历,树型DP与模拟

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/36741.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

第一章:光纤通信概述

第一节&#xff1a;通信基本概念 1.1光纤通信基本概念 1.1.1光纤通信的概念 利用光导纤维传输广播信号的通信方式称为光纤通信。光波主要包括紫外线、可见光和红外线。光纤通信工作波长在近红外区&#xff0c;0.8um~1.8um的波长区&#xff0c;频率为167THz~375THz。光纤基础…

Nuxt3引入Element-plus和sass

1.引入Element-plus 打开编辑器终端 运行npm install element-plus/nuxt 或者命令行cd到项目文件 运行npm install element-plus/nuxt package.json文件会出现 使用Element-plus 在nuxt.config.ts文件添加代码 export default defineNuxtConfig({devtools: { enabled: true }…

MFC学习日记(一)——创建新项目

此系列所有文章参考链接&#xff1a;http://www.jizhuomi.com/software/141.html 点击file新建项目创建一个MFC新项目 点击确定 点击下一步 选择应用程序类型 我们看到有四种类型&#xff1a;Single document&#xff08;单文档&#xff09;、Multiple documents&#xff…

gigachad1靶机详解

gigachad_vh靶机详解 扫描到ip后对ip做一个全面扫描&#xff0c;发现有一个匿名服务器&#xff0c;是可以免密登陆的。 登陆上后发现就一个文件&#xff0c;get到我们电脑上。 file一下发现是一个zip文件&#xff0c;unzip解压一下&#xff0c;发现给了一个用户名chad&#xf…

【数据挖掘】时间序列教程【二】

2.4 示例:颗粒物浓度 在本章中,我们将使用美国环境保护署的一些空气污染数据作为运行样本。该数据集由 2 年和 5 年空气动力学直径小于或等于 3.2017 \(mu\)g/m\(^2018\) 的颗粒物组成。 我们将特别关注来自两个特定监视器的数据,一个在加利福尼亚州弗雷斯诺,另一个在密…

软考:中级软件设计师:存储管理,分区存储,页式存储,逻辑地址,物理地址

软考&#xff1a;中级软件设计师:存储管理&#xff0c;分区存储 提示&#xff1a;系列被面试官问的问题&#xff0c;我自己当时不会&#xff0c;所以下来自己复盘一下&#xff0c;认真学习和总结&#xff0c;以应对未来更多的可能性 关于互联网大厂的笔试面试&#xff0c;都是…

LLM - Baichuan7B Tokenizer 生成训练数据

目录 一.引言 二.Tokenizer 原始数据 1.原始数据样例 2.加载并 Token 原始数据 2.1 参数准备 2.2 单条样本处理逻辑 2.3 批量处理逻辑 2.4 主函数与完整代码 三.shell 执行 四.总结 一.引言 前面提到了自己在微调 Baichuan7B Lora 的过程中遇到了一些问题&#xff0c…

leetcode 236. 二叉树的最近公共祖先

2023.7.11 这道题是道面试高频题&#xff0c;并且有点抽象。 首先确定终止条件。如果根节点为空&#xff0c;或者其中一个节点是根节点本身&#xff08;即 p root 或 q root&#xff09;&#xff0c;那么根节点就是它们的最低共同祖先&#xff0c;因此我们直接返回根节点 roo…

产品经理怎么管理项目进度?

作为在职七年的项目管理人员&#xff0c;在项目进度管理上确实有一点发言权。产品经理作为企业的核心骨干岗位之一&#xff0c;在进行项目进度管理时也会有很多问题出现&#xff0c;那么应该怎样去管理项目进度呢&#xff1f;以下是答主的一些拙见&#xff0c;有需要的朋友们就…

接口测试之postman使用详解

我们平常要做接口测试时&#xff0c;可能需要使用一些工具&#xff0c;其实最简单的的做接口测试的工具就是postman&#xff0c;它可以用来模拟http中的get、post接口等&#xff0c;然后我们去验证接口的返回参数及数据是否符合我们的逻辑。那么怎么使用呢&#xff1f;也就是今…

C++之工厂模式

目录 一、为什么要使用工厂模式 优点 缺点 二、简单工厂&#xff08;Simple Factory&#xff09; 好处&#xff1a; 不足&#xff1a; 三、工厂方法&#xff1a; 好处&#xff1a; 不足&#xff1a; 四、抽象工厂&#xff08;Abstract Factory&#xff09; 一、为什…

【工具推荐】企业微信、企业飞书接口调用工具

github地址: GitHub - fasnow/idebug: 企业微信、企业飞书接口调用工具。 简介 企业微信、企业飞书接口调用工具。 使用方法 wechat模块 使用use wechat 选择模块。 首先设置corpid和corpsecret&#xff0c;如有需要可以设置代理&#xff0c;之后再执行run命令。 导出通信…

chatgpt 与传统3D建模对比分析

推荐&#xff1a;将NSDT场景编辑器加入你的3D工具链 随着人工智能技术的发展&#xff0c;越来越多的领域正逐渐被AI模型所取代。ChatGPT作为一种自然语言处理技术&#xff0c;越来越为人们所熟悉。最近&#xff0c;一些3D建模领域的专家想知道ChatGPT是否可以取代传统的手动3D建…

在?聊聊浏览器事件循环机制

目录 前言 同步/异步编程模型 同步 异步 JS异步模型 调用栈 任务队列 宏任务队列 微任务队列 微任务API 事件循环 队列优先级 混合队列 事件循环实现 总结 参考文章 Event-Loop可视化工具 前言 JS是单线程语言&#xff0c;在某个时间段只能执行一段代码。这…

IP地址定位技术为何如此准确?揭秘背后原理

据最新数据显示&#xff0c;全球互联网用户数量已突破50亿。为确保用户安全和提供个性化服务&#xff0c;IP地址定位技术愈发重要。但你是否好奇&#xff0c;为何IP地址定位如此准确&#xff1f;今天我们将揭秘其背后原理。 IP地址定位技术利用了多种方法来确定用户的地理位置。…

mac苹果电脑,怎么把mkv转换mp4格式

mac苹果电脑&#xff0c;怎么把mkv转换mp4格式&#xff1f;如果你是一名mac苹果电脑的用户&#xff0c;在电脑上下载到mkv格式的视频后会发现它使用起来非常的麻烦&#xff0c;甚至不能直接打开播放。mkv其实也是一种时间比较久远的视频文件格式&#xff0c;但是不知道是什么原…

MAC电脑查看SHA256方式

背景 现在很多网站下载大文件时&#xff0c;以往通过查看文件大小来确定是否下载正确&#xff0c;但是很多情况下&#xff0c;文件下载后大小差不多&#xff0c;但是很多时候却时候出现无法安装的问题&#xff0c;有可能还是下载的文件出现错误&#xff0c;导致文件无法正常使…

研发效能认证学员作品:使用威胁建模进行DevSecOps实践

一、从DevOps到 DevSecOps 作者&#xff1a; 姚圣伟&#xff08;现就职天津引元科技 天津市区块链技术创新中心&#xff09; 研发效能&#xff08;DevOps&#xff09;工程师认证学员 DevOps 最开始最要是强调开发和运维的协作与配合&#xff0c;至今&#xff0c;已不仅仅涉及开…

【运维工程师学习二】OS系统管理

【运维工程师学习二】OS系统管理 1、操作系统管理2、进程管理3、进程的启动4、进程信息的查看4.1、STAT 进程的状态&#xff1a;进程状态使用字符表示的&#xff08;STAT的状态码&#xff09;,其状态码对应的含义&#xff1a;4.2、ps命令常用用法&#xff08;方便查看系统进程&…

stm32(独立看门狗和窗口看门狗)

独立看门狗介绍 什么是看门狗&#xff1f; 在由单片机构成的微型计算机系统中&#xff0c;由于单片机的工作常常会受到来自外界电磁场的干扰&#xff0c;造 成程序的跑飞&#xff0c;而陷入死循环&#xff0c;程序的正常运行被打断&#xff0c;由单片机控制的系统无法继续工作…