大纲
● 654.最大二叉树
● 617.合并二叉树
● 700.二叉搜索树中的搜索
● 98.验证二叉搜索树
最大二叉树
题目:654.最大二叉树
需要通过数组构造一个二叉树,根节点是最大值的二叉树
思路是找到子数组内最大元素,分割为左右子数组,然后构建节点进行返回
// 最大二叉树
// 递归退出条件:subArr为空
// 递归参数 subArr
// 单层循环:左右子数组 返回新建立的node
TreeNode* getMaxTree(vector<int>& subArr) {
if (subArr.empty()) return nullptr;
int maxIndex = 0;
for (int i = 1; i < subArr.size(); ++i) {
if (subArr[i] > subArr[maxIndex])
maxIndex = i;
}
vector<int> leftArr(subArr.begin(), subArr.begin() + maxIndex);
vector<int> rightArr(subArr.begin() + maxIndex + 1, subArr.end());
TreeNode* left = getMaxTree(leftArr);
TreeNode* right = getMaxTree(rightArr);
TreeNode* node = new TreeNode(subArr[maxIndex]);
node->left = left;
node->right = right;
return node;
}
合并二叉树
题目:617.合并二叉树
本题需要合并两个树,同一个节点值相加,无节点则合并,返回合并后的树根节点
思路是通过递归,保存根节点,分别遍两个树的节点,进行合并。
递归的结束条件是节点是左右节点都为空节点了,否则就判断是否需要合并节点,返回值是合并后的节点。最后在更新根节点。
// 合并二叉树
// 递归思路
// 递归返回值:树
// 递归结束条件:root1 root2是否为空
// 递归循环:
TreeNode* rootParent = nullptr;
TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2)
{
if (!root1 && !root2) return nullptr;
if (!root1) {
TreeNode* node = new TreeNode(root2->val);
root1 = node;
}
if (root1 && root2)
root1->val += root2->val;
TreeNode* left = mergeTrees(root1 ? root1->left : nullptr, root2 ? root2->left : nullptr);
TreeNode* right = mergeTrees(root1 ? root1->right : nullptr, root2 ? root2->right : nullptr);
if (rootParent) {
rootParent->left = left;
rootParent->right = right;
rootParent = root1;
} else {
rootParent = root1;
}
return root1;
}
二叉搜索树中的搜索
题目:700.二叉搜索树中的搜索
本题给的树是二叉搜索树,二叉搜索树的特性是根节点是最大值,且满足节点值大于左节点且小于右节点。使用中序遍历就是将数据从小到大排序了。
思路是通过遍历节点,利用二叉搜索树的特性来判断来减少遍历次数。
使用的是遍历,代码如下:
// 二叉搜索树中的搜索
TreeNode* searchBalanceTree(TreeNode* root, int val)
{
TreeNode *node = root;
while (node) {
if (node->val > val) {
node = node->left;
} else if (node->val < val) {
node = node->right;
} else {
return node;
}
}
return nullptr;
}
验证二叉搜索树
题目:98.验证二叉搜索树
本题需要验证树是不是二叉搜索树,需要验证是否满足二叉搜索树的特性
本题的递归解法代码如下,但是是有问题的,没有比较左右子树,仅比较了左右节点
// 递归
// 结束条件:节点为空节点孩子为空
// 判断过程:左右节点的值是否满足条件
bool isSearchBalancTree(TreeNode* root)
{
if (!root) return true;
if (root->left && root->val <= root->left->val) {
return false;
}
if (root->right && root->val >= root->right->val) {
return false;
}
return isSearchBalancTree(root->left) && isSearchBalancTree(root->right);
}
正确做法:
判断中序遍历是否是有序的,代码如下:
// 算法错误在于不能单纯比较左右节点和根节点,
// 而是需要比较左右子树和根节点,
// 所以需要使用中序遍历,在判断是否有序
void inorderReverse(TreeNode* root, vector<int>& ret) {
if (!root) return;
inorderReverse(root->left, ret);
ret.push_back(root->val);
inorderReverse(root->right, ret);
}
bool isVailanTree(TreeNode* root)
{
vector<int> ret;
// 中序遍历
inorderReverse(root, ret);
// 判断有序
for (int i = 1; i < ret.size(); ++i) {
if (ret[i - 1] >= ret[i])
return false;
}
return true;
}
总结
本章节的二叉树算法在解题上有一定的相似性,需要多总结出适合自己的解题方式