LeetCode | C++ 654.最大二叉树、617.合并二叉树、700.二叉搜索树中的搜索、98.验证二叉搜索树

52 篇文章 0 订阅

654.最大二叉树

构造最大二叉树,与105、106 题目类似

注意: 凡是构造二叉树的题目一律用前序遍历

前序遍历是 中左右, 因为只有构造了中结点, 才能去构造它的左右孩子结点

class Solution {
public:
    TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
        return traversal(nums, 0, nums.size());
    }
    TreeNode* traversal(vector<int>& nums, int numsBegin, int numsEnd) {
        if (numsBegin >= numsEnd) return NULL;
        TreeNode* node;
        
        int maxId = numsBegin;
        for (int i = numsBegin + 1; i < numsEnd; i++) {
            if (nums[i] > nums[maxId]) maxId = i;
        }
        node = new TreeNode(nums[maxId]);
        // 左闭右开[ )
        int numsLeftBegin = numsBegin;
        int numsLeftEnd = maxId;

        int numsRightBegin = maxId + 1;
        int numsRightEnd = numsEnd;

        node->left = traversal(nums, numsLeftBegin, numsLeftEnd);
        node->right = traversal(nums, numsRightBegin, numsEnd);
        return node;
    }
};

617.合并二叉树

使用递归前中后序遍历都是可以的,只不过前序遍历是最容易理解的。

为了减小空间的损耗,不去定义新的树,直接在树1的基础之上该变其结构。

class Solution {
public:
    TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
        return traversal(root1, root2);
    }
    TreeNode* traversal(TreeNode* tree1, TreeNode* tree2) {
        if (tree1 == NULL) return tree2;
        if (tree2 == NULL) return tree1;
        tree1->val += tree2->val;
        tree1->left = traversal(tree1->left, tree2->left);
        tree1->right = traversal(tree1->right, tree2->right);
        return tree1;
    }
};

700.二叉搜索树中的搜索

二叉搜索树是一个有序树:

  • 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
  • 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
  • 它的左、右子树也分别为二叉搜索树

二叉搜索树自身特性,帮助我们明确了搜索的方向

遇到搜索树,一定要想着中序遍历 : 左 中 右,这样才能利用上特性。

class Solution {
public:
    // 迭代法
    TreeNode* searchBST(TreeNode* root, int val) {
        while (root != NULL) {
            if (val < root->val) root = root-> left;
            else if (val > root->val) root = root->right;
            else return root;
        }
        return NULL;
    }
};
class Solution {
public:
    // 递归法
    TreeNode* searchBST(TreeNode* root, int val) {
        if (root == NULL || root->val == val) return root;
        TreeNode* result = NULL;
        if (val < root->val) {
            result = searchBST(root->left, val);
        }
        if (val > root->val) {
            result = searchBST(root->right, val);
        }
        return result;
    }
};

98.验证二叉搜索树

按照 二叉搜索树的特性去遍历,看其是否是一个 有序数组。即:对于二叉搜索树来说,使用 中序遍历得到 的数组为一个递增 的数组。

对于判断一个数组是否有序,可以不需要额外去定义一个变量来比较,可以通过前后两者进行比较,对于二叉树而言,即为前一个结点和后一个结点进行比较。

对于该题而言,结点的值中会出现int 类型的最小值,所以在比较时,我们只能比int 最小值还要小,所以定义的为 long long max val = long_min

暴力法

class Solution {
public:
    // 暴力法:按照 二叉搜索树的特性去遍历,看其是否是一个 有序数组。
    vector<int> nums;
    bool isValidBST(TreeNode* root) {
        nums.clear();
        long long max = LONG_MIN;
        traversal(root);
        for (int i : nums) {
            std::cout << i << endl;
            if (i > max) {
                max = i;
            }
            else {
                return false;
            }
        }
        return true;
    }
    void traversal(TreeNode* node) {
        if (node == NULL) return;
        traversal(node->left);
        nums.push_back(node->val);
        traversal(node->right);
        return;
    }
};

递归法

class Solution {
public:
    // 递归法1
    long long max = LONG_MIN;
    bool isValidBST(TreeNode* root) {
        if (root == NULL) return true;
        
        bool left = isValidBST(root->left);

        if (root->val > max) {
            max = root->val;
        } else return false;

        bool right = isValidBST(root->right);
        return left && right;
    }
};

递归法 双指针优化

class Solution {
public:
    // 递归法2:利用双指针法 对其进行优化
    TreeNode* pre = NULL; // 指向当前结点的前一个结点(往下)
    bool isValidBST(TreeNode* root) {
        if (root == NULL) return true;
        bool left = isValidBST(root->left);
        if (pre != NULL && pre->val >= root->val) return false;
        pre = root;
        bool right = isValidBST(root->right);
        return left && right;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值