目 录CONTENT

文章目录

Day20 二叉树构建 | 二叉搜索树

如风
2023-03-19 / 0 评论 / 0 点赞 / 23 阅读 / 1,640 字

Day20 二叉树构建 | 二叉搜索树

今日内容

● 654.最大二叉树

● 617.合并二叉树

● 700.二叉搜索树中的搜索

● 98.验证二叉搜索树

654. 最大二叉树

给定一个不重复的整数数组 nums最大二叉树 可以用下面的算法从 nums 递归地构建:

  1. 创建一个根节点,其值为 nums 中的最大值。
  2. 递归地在最大值 左边子数组前缀上 构建左子树。
  3. 递归地在最大值 右边子数组后缀上 构建右子树。

返回 nums 构建的 *最大二叉树*

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func constructMaximumBinaryTree(nums []int) *TreeNode {
    // 思路:先找到最大值及其下标, 作为根节点,递归左右
    if len(nums) == 0 {
        return nil
    }
    j, maxv := 0, math.MinInt64
    for i := 0; i < len(nums); i ++ {
        if nums[i] > maxv {
            maxv = nums[i]
            j = i 
        }
    }
    root := &TreeNode{}
    root.Val = maxv
    root.Left = constructMaximumBinaryTree(nums[:j])
    root.Right = constructMaximumBinaryTree(nums[j+1:])
    return root
}

C++实现

/**
 * 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* constructMaximumBinaryTree(vector<int>& nums) {
        if(nums.size() == 0) return nullptr;
        vector<int> left, right;
        int idx = getMaxIndex(nums);
        for(int i = 0; i < idx; i ++ ) left.push_back(nums[i]);
        for(int i = idx + 1; i < nums.size(); i ++ ) right.push_back(nums[i]);
        TreeNode* root = new TreeNode(nums[idx]);
        root->left = constructMaximumBinaryTree(left);
        root->right = constructMaximumBinaryTree(right);
        return root;
    }
    int getMaxIndex(vector<int>& nums) {
        int res = 0, flag = nums[0];
        for(int i = 0; i < nums.size(); i ++ ) {
            if(nums[i] > flag) {
                res = i;
                flag = nums[i];
            }
        }
        return res;
    }
            
};

617. 合并二叉树

给你两棵二叉树: root1root2

想象一下,当你将其中一棵覆盖到另一棵之上时,两棵树上的一些节点将会重叠(而另一些不会)。你需要将这两棵树合并成一棵新二叉树。合并的规则是:如果两个节点重叠,那么将这两个节点的值相加作为合并后节点的新值;否则,不为 null 的节点将直接作为新二叉树的节点。

返回合并后的二叉树。

注意: 合并过程必须从两个树的根节点开始。

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func mergeTrees(root1 *TreeNode, root2 *TreeNode) *TreeNode {
    // 思路:将根节点的值 计算出来,然后递归进行构造
    if root1 == nil && root2 == nil {
        return nil
    }
    if root1 == nil {
        return root2
    }
    if root2 == nil {
        return root1
    }
    val := root1.Val + root2.Val
    root := &TreeNode{}
    root.Val = val
    root.Left = mergeTrees(root1.Left, root2.Left)
    root.Right = mergeTrees(root1.Right, root2.Right)
    return root
}

C++实现

/**
 * 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* mergeTrees(TreeNode* root1, TreeNode* root2) {
        if(root1 == nullptr) return root2;
        if(root2 == nullptr) return root1;
        // if(root1 && root2) {
        //     TreeNode* tmp = new TreeNode(root1->val + root2->val);
        //     return tmp;
        // }

        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

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func searchBST(root *TreeNode, val int) *TreeNode {
    // 思路:判断根节点和val的大小关系 决定寻找的方向
    if root == nil {
        return nil
    }
    if root.Val > val {
        return searchBST(root.Left, val)
    }else if root.Val < val {
        return searchBST(root.Right, val)
    }
    return root
}

C++ 实现

/**
 * 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* 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);

        return root;
    }
};

98. 验证二叉搜索树

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

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

  • 节点的左子树只包含 小于 当前节点的数。
  • 节点的右子树只包含 大于 当前节点的数。
  • 所有左子树和右子树自身必须也是二叉搜索树。
/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func isValidBST(root *TreeNode) bool {
    // 思路:利用二叉搜索树的前序遍历是单调递增的特性
    if root == nil {
        return true
    }
    return help(root, math.MinInt64, math.MaxInt64)
}

func help(root *TreeNode, left, right int) bool{
    if root == nil {
        return true
    }
    if root.Val <= left || root.Val >= right {
        return false
    }
    // 递归的往下进行比较
    return help(root.Left, left, root.Val) && help(root.Right, root.Val, right)
}

C++ 实现

/**
 * 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) {
        if(root == nullptr) return true;
        return helper(root, LONG_MIN, LONG_MAX);
    }
    bool helper(TreeNode* root, long int left, long int right) {
        if(root == nullptr) return true;
        if(root->val <= left || root->val >= right) return false;
        return helper(root->left, left, root->val) && helper(root->right, root->val, right);
    }
};
/**
 * 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) {
        if(root == nullptr) return true;
        vector<int> nums;
        helper(root, nums);
        for(int i = 1; i < nums.size(); i ++ ) if(nums[i] <= nums[i - 1]) return false;
        return true;
    }
    void helper(TreeNode* root, vector<int>& nums) {
        if(root == nullptr) return;
        helper(root->left, nums);
        nums.push_back(root->val);
        helper(root->right, nums);
        return;
    }
};

总结

  • 最大二叉树和合并二叉树本质上都是构造二叉树,只不过规则变了,一个是要找到最大的值,一个需要进行值的合并
  • 二叉搜索树中搜索元素很简单,按照特性来搜索就行了
  • 判断就有点复杂了,因为要保证左边左右的都要小于根节点,右边所有的都要大于根节点。所以我们可以利用二叉搜索的另一个特性就是:前序遍历的结果是单调递增的序列。给定两个边界值来限定他们的比较,递归下去所以是从最下来开始比较
0

评论区