代码随想录算法训练营第二十天|654.最大二叉树、617.合并二叉树、700.二叉搜索树中的搜索、98.验证二叉搜索树

LeetCode 654 最大二叉树

题目链接:https://leetcode.cn/problems/maximum-binary-tree/

思路:

我的思路是和昨天的前序与中序(中序与后序)构造二叉树的思路基本一样。

代码:

  • 完整版-使用新数组

/**
 * 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.empty())    return nullptr;
        return traversal(nums);

    }

    TreeNode* traversal(vector<int>&nums)
    {
        // 第一步
        // 处理空节点
        if(nums.size()==0)  return nullptr;

        // 第二步
        // 寻找节点元素
        int Max = 0;
        int index = 0;
        for(int i = 0;i<nums.size();i++)
        {
            if(nums[i]>Max)
            {
                Max = nums[i];
                index = i;
            }
        }

        // cout<<index<<endl;

        TreeNode *root = new TreeNode(Max);

        // 第三步
        // 分割左右数组
        vector<int>left(nums.begin(),nums.begin()+index);
        vector<int>right(nums.begin()+index+1,nums.end());

        // cout<<"------------------------"<<endl;;
        // cout<<"left:"<<endl;
        // for(int i:left)
        //     cout<<i<<" ";
        // cout<<endl;

        // cout<<"right:"<<endl;
        // for(int i:right)
        //     cout<<i<<" ";
        // cout<<endl;

        // 第四步
        // 递归左右子树
        root->left = traversal(left);
        root->right = traversal(right);

        return root;
    }




};
  • 优化版-使用下标

/**
 * 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.empty())    return nullptr;
        return traversal(nums,0,nums.size());

    }

    TreeNode* traversal(vector<int>&nums,int left,int right)
    {
        // 第一步
        // 处理空节点
        if(left>=right)  return nullptr;

        // 第二步
        // 寻找节点元素
        int index = left;
        for(int i = left+1;i<right;i++)
        {
            if(nums[i]>nums[index])
                index = i;
        }

        TreeNode *root = new TreeNode(nums[index]);

        // 第三步
        // 递归左右子树
        root->left = traversal(nums,left,index);
        root->right = traversal(nums,index+1,right);

        return root;
    }
};

总结

和昨天通过遍历方式构造二叉树类似,使用数组的方法自己可以完整写出来。使用下标的方法,在计算下标处还是有问题。

LeetCode 617 合并二叉树

题目链接:https://leetcode.cn/problems/merge-two-binary-trees/

思路:

采用前序遍历进行合并

代码:

/**
 * 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)  return root2;
        if(!root2)  return root1;

        // 中
        TreeNode *root = new TreeNode(0);
        root->val = root1->val+root2->val;

        // 左
        root->left = mergeTrees(root1->left,root2->left);

        // 右
        root->right = mergeTrees(root1->right,root2->right);

        return root;
    }
};

总结

没有想象中那么复杂,算是第一道显性的操作两棵二叉树的题目。

LeetCode 700 二叉搜索树中的搜索

题目链接:https://leetcode.cn/problems/search-in-a-binary-search-tree/

思路:

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

  • 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;

  • 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;

  • 它的左、右子树也分别为二叉搜索树

所以如果给的值小于根节点的值,那么我们往它的左子树去寻找;如果大于,那么往右子树方向去寻找。

代码:

递归法:
  • 自写

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

        TreeNode *result = new TreeNode();
        
        if(root->val>val)
            result = searchBST(root->left,val);
        if(root->val<val)
            result = searchBST(root->right,val);

        return result;
    }
};
  • 简洁版

/**
 * 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||root->val==val)   return root;
        
        if(root->val>val)   return searchBST(root->left,val);
        if(root->val<val)   return searchBST(root->right,val);

        return nullptr;
    }
};
迭代法
/**
 * 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) {
        while(root)
        {
            if(root->val>val)   root = root->left;
            else if(root->val<val)  root = root->right;
            else    return root;
        }
        return nullptr;
    }
};

总结

要利用二叉搜索树(BFS)的特性来进行遍历。

LeetCode 98 验证二叉搜索树

题目链接:https://leetcode.cn/problems/validate-binary-search-tree/

思路:

在中序遍历下二叉搜索树是一个有序数组。

注:空节点也是二叉搜索树。

陷阱

陷阱1:

不能单纯的仅仅比较左节点小于中间节点,右节点大于中间节点

写出类似的代码:

if (root->val > root->left->val && root->val < root->right->val) {
    return true;
} else {
    return false;
}

这样是错误的。因为我们要求的是左右子树都满足二叉搜索树的特性,即左子树所有节点小于中间节点,右子树所有节点大于中间节点

很容易出现这样的错误:

陷阱2:

在leetcode中最小节点可以取到int的最小值,所以使用最小的int来比较是不行的。

此时可以初始化比较元素为longlong的最小值。

然而,问题可以进一步延展:如果leetcode中根节点的val 可能是longlong的最小值,又要怎么办呢?

答:此时我们就可以定义一个TreeNode*记录前一个节点,用前一个节点与当前节点做比较,从而避免了使用最小值。

代码:

  • 利用中序遍历递归法

/**
 * 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:
    vector<int>result;

    bool isValidBST(TreeNode* root) {
        result.clear();
        inorder(root);

        for(int i = 1;i<result.size();i++)
        {
            if(result[i]<=result[i-1])
                return false;
        }
        return true;
    }

    void inorder(TreeNode *cur)
    {
        if(!cur)    return;
        inorder(cur->left);
        result.push_back(cur->val);
        inorder(cur->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:
    TreeNode *pre = nullptr;    // 用来记录前一个节点

    bool isValidBST(TreeNode* root) {
        // 终止条件
        if(!root)   return true;

        // 左
        bool left = isValidBST(root->left);

        // 中
        if(pre&&pre->val>=root->val)    return false;   // 二叉搜索树不能有相同元素

        // 更新pre
        pre = root;

        // 右
        bool right = isValidBST(root->right);

        return left&&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)   return true;
        stack<TreeNode*>st;
        TreeNode *cur = root;
        TreeNode *pre = nullptr;
        while(cur||!st.empty())
        {
            if(cur)
            {
                st.push(cur);
                cur = cur->left;
            }
            else
            {
                cur = st.top();
                st.pop();
                if(pre&&pre->val>=cur->val)
                    return false;
                
                pre = cur;

                cur = cur->right;
            }
        }
        return true;

    }
};

总结

要记住遇到二叉搜索树,要想着中序遍历,从而发挥出二叉搜索树的特性。因为中序遍历可以将二叉搜索树遍历成一个有序的数组。

今日总结:

学到了二叉搜索树,复习了中序遍历的迭代法。可以写出来最大二叉树的题目,将昨天学到的内容也复习了。、收获很多,继续加油!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值