day20 代码回想录 最大二叉树&合并二叉树&二叉搜索树中的搜索&验证二叉搜索树

大纲

● 654.最大二叉树
● 617.合并二叉树
● 700.二叉搜索树中的搜索
● 98.验证二叉搜索树

最大二叉树

题目:654.最大二叉树
需要通过数组构造一个二叉树,根节点是最大值的二叉树
思路是找到子数组内最大元素,分割为左右子数组,然后构建节点进行返回

// 最大二叉树
// 递归退出条件:subArr为空
// 递归参数 subArr
// 单层循环:左右子数组 返回新建立的node
TreeNode* getMaxTree(vector& 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 leftArr(subArr.begin(), subArr.begin() + maxIndex);
    vector 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& ret) {
    if (!root) return;

    inorderReverse(root->left, ret);
    ret.push_back(root->val);
    inorderReverse(root->right, ret);
}

bool isVailanTree(TreeNode* root)
{
    vector ret;
    // 中序遍历
    inorderReverse(root, ret);
    // 判断有序
    for (int i = 1; i < ret.size(); ++i) {
        if (ret[i - 1] >= ret[i])
            return false;
    }
    return true;
}

总结

本章节的二叉树算法在解题上有一定的相似性,需要多总结出适合自己的解题方式

你可能感兴趣的:(数据结构,算法,c++,leetcode,二叉树)