LeetCode 代码随想录跟练 Day17
- 654.最大二叉树
- 617.合并二叉树
- 700.二叉搜索树中的搜索
- 98.验证二叉搜索树
654.最大二叉树
题目描述:
给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建:
创建一个根节点,其值为 nums 中的最大值。
递归地在最大值 左边 的 子数组前缀上 构建左子树。
递归地在最大值 右边 的 子数组后缀上 构建右子树。
返回 nums 构建的 最大二叉树 。
在数组上构建二叉树,思路很直观,只需注意取到最大值后左右子树的边界,traverse使用left和right表示当前递归所使用到的数组的区间。代码如下:
class Solution {
private:TreeNode* traverse(vector<int>& nums, int left, int right) {if (left > right) return nullptr;int maxVal = nums[left];int maxIndex = left;for (int i = left + 1; i <= right; ++i) {if (nums[i] > maxVal) {maxVal = nums[i];maxIndex = i;}}TreeNode* root = new TreeNode(maxVal);root->left = traverse(nums, left, maxIndex - 1);root->right = traverse(nums, maxIndex + 1, right);return root;}public:TreeNode* constructMaximumBinaryTree(vector<int>& nums) {return traverse(nums, 0, nums.size() - 1);}
};
617.合并二叉树
题目描述:
给你两棵二叉树: root1 和 root2 。
想象一下,当你将其中一棵覆盖到另一棵之上时,两棵树上的一些节点将会重叠(而另一些不会)。你需要将这两棵树合并成一棵新二叉树。合并的规则是:如果两个节点重叠,那么将这两个节点的值相加作为合并后节点的新值;否则,不为 null 的节点将直接作为新二叉树的节点。
返回合并后的二叉树。
注意: 合并过程必须从两个树的根节点开始。
示例 1:
输入:root1 = [1,3,2,5], root2 = [2,1,3,null,4,null,7]
输出:[3,4,5,5,4,null,7]
示例 2:
输入:root1 = [1], root2 = [1,2]
输出:[2,2]
实际上还是对二叉树的遍历,每次遍历的参数为两个二叉树各自位置的当前节点。不同的是在初值判断的过程中,若其中一个节点为空则直接返回另一个节点作为合并后的节点,其他过程使用前序遍历即可。代码如下:
class Solution {
public:TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {if (root1 == nullptr) return root2;if (root2 == nullptr) return root1;TreeNode* root = new TreeNode(root1->val + root2->val);root->left = mergeTrees(root1->left, root2->left);root->right = mergeTrees(root1->right, root2->right);return root;}
};
700.二叉搜索树中的搜索
题目描述:
给定二叉搜索树(BST)的根节点 root 和一个整数值 val。
你需要在 BST 中找到节点值等于 val 的节点。 返回以该节点为根的子树。 如果节点不存在,则返回 null 。
二叉搜索树是指树中每个节点值均大于其左子树所有节点值并小于其右子树的所有节点值的二叉树。题目执行的搜索操作,根据迭代能够直观的找到结果:
class Solution {
public:TreeNode* searchBST(TreeNode* root, int val) {while (!root) {if (root->val == val) return root;else if (root->val > val) root = root->left;else if (root->val < val) root = root->right;}return nullptr;}
};
按照递归方法同二叉树递归框架:
class Solution {
public:TreeNode* searchBST(TreeNode* root, int val) {if (root == nullptr) return nullptr;if (root->val == val) {return root;} else if (root->val > val) {return searchBST(root->left, val);} else {return searchBST(root->right, val);}}
};
98.验证二叉搜索树
题目描述:
给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。
有效 二叉搜索树定义如下:
节点的左子树只包含 小于 当前节点的数。
节点的右子树只包含 大于 当前节点的数。
所有左子树和右子树自身必须也是二叉搜索树。
判断一个树是否是二叉搜索树最简单的逻辑:其左右子树是否是二叉搜索树,当前节点值是否大于左节点小于右节点。但是直接这样做会陷入一个局部解,对每个局部子树都是二叉搜索树的判断无法得出树整体是一个二叉搜索树,如下图
比如这里的两个子树都是二叉搜索树,但整体上根节点的左子树中有 5 > 3 5>3 5>3,不满足二叉搜索树的条件,所以在递归的同时需传入边界,向左子树前进时需传入根节点的值作为最大值的限制,向右子树前进时需传入根节点的值作为最小值的限制。代码如下:
class Solution {
private:bool traverse(TreeNode* root, long long min, long long max) {if (root == nullptr) return true;if (root->val <= min || root->val >= max) return false;return traverse(root->left, min, root->val) && traverse(root->right, root->val, max);}public:bool isValidBST(TreeNode* root) {return traverse(root, LONG_MIN, LONG_MAX);}
};
注意在判断时使用大于等于和小于等于(二叉搜索树中不能有相同元素)