代码随想录算法训练营第十七天| leetcode 654、617、700、98

凡是构造二叉树的题目都要用前序遍历

因为前序是中左右,先构造根节点,后构造根节点的左右子树。

最大二叉树 leetcode 654

解法一:递归

首先,确定递归函数的返回值和传入的参数,返回值就是构造的二叉树的根节点,输入参数就是一个数组。

其次,确定递归函数结束的条件,因为题目规定数组不为空,所以当数组大小为一也就是叶子节点时递归结束。

最后,确定单层递归的逻辑。首先找到数组中的最大值及其下标,当下标大于0时构建其左子树,当下标小于数组大小-1时构建其右子树。

class Solution {
public:
    TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
        if(nums.size()==1) return new TreeNode(nums[0]);
        int maxValue=0;
        int index=0;
        for(int i=0;i<nums.size();i++){
            if(nums[i]>maxValue){
                maxValue=nums[i];
                index=i;
            }
        }
        TreeNode* node=new TreeNode(nums[index]);;
        if(index>0){
            vector<int> vecNew(nums.begin(),nums.begin()+index);
            node->left=constructMaximumBinaryTree(vecNew);
        }
        if(index<nums.size()-1){
            vector<int> vecNew(nums.begin()+index+1,nums.end());
            node->right=constructMaximumBinaryTree(vecNew);
        }
        return node;
    }
};

解法一优化

因为每次构造左右子树都需要构造新的数组,效率不高,我们采用传入新的数组下标来构建左右子树。

class Solution {
public:
    TreeNode* traversal(vector<int>& nums,int left,int right){
        if(left>=right) return nullptr;
        int max_index=left;
        for(int i=left+1;i<right;i++){
            if(nums[i]>nums[max_index]) max_index=i;
        }
        TreeNode* node=new TreeNode(nums[max_index]);
        node->left=traversal(nums,left,max_index);
        node->right=traversal(nums,max_index+1,right);
        return node;
    }
    TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
        return traversal(nums,0,nums.size());
    }
};

出现的错误

1.找最大值索引的for循环中条件写成了i<nums.size(),因为数组大小是不变得,这样写递归第一次之和都会越界。

递归函数前什么时候加if?

如果让空节点(空指针)进入递归,就不加if,如果不让空节点进入递归,就加if限制一下, 终止条件也会相应的调整。

合并二叉树  leetcode 617

解法:递归

首先,确定返回值和传入参数,返回新二叉树根节点,传入两个二叉树的根节点。

其次,确定递归结束条件,当一个树根节点为空时,返回另一个二叉树对应位置。

最后,确定单层递归逻辑,单层递归逻辑就是除了我们写的if递归结束条件之外的情况我们应该做什么,在其中一个树上操作,将两树对应节点的value加起来。

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

二叉搜素树中的搜索 leetcode 700

解法一:递归

确定递归结束的条件,当当前节点为空或者当前节点value等于传进来的参数value,就返回这个节点。

单层递归逻辑,根据二叉搜索树的特性,如果当前节点的value小于目标值,那就递归遍历节点的左子树,如果大于目标值,那就递归遍历节点的右子树。

class Solution {
public:
    TreeNode* searchBST(TreeNode* root, int val) {
        if(root==nullptr||root->val==val) return root;
        TreeNode* res=nullptr;
        if(root->val<val) res=searchBST(root->right,val);
        if(root->val>val) res=searchBST(root->left,val);
        return res;
    }
};

解法二:迭代

鄙人自己写得

class Solution {
public:
    TreeNode* searchBST(TreeNode* root, int val) {
        if(root==nullptr||root->val==val) return root;
        stack<TreeNode*> st;
        st.push(root);
        TreeNode* res=nullptr;
        while(!st.empty()){
            TreeNode* cur=st.top();
            st.pop();
            if(cur->val==val){
                res=cur;
                return res;
            }
            if(cur->val<val&&cur->right) st.push(cur->right);
            if(cur->val>val&&cur->left) st.push(cur->left);
        }
        return res;
    }
};

卡哥代码随想录版本

class Solution {
public:
    TreeNode* searchBST(TreeNode* root, int val) {
        while(root!=nullptr){
            if(root->val>val) root=root->left;
            else if(root->val<val) root=root->right;
            else return root;
        }
        return root;
    }
};

总结

还是太菜了我,还得练,一个while循环就可以解决得问题,想得太复杂。

验证二叉搜索树 leetcode 98

解法一:使用数组判断

根据二叉搜索树的特性,我们采用中序遍历把所有的元素放入一个数组,如果这个数组是单调递增的那么这个数就是二叉搜索树。

class Solution {
public:
    vector<int> vec;
    void traversal(TreeNode* root){
        if(root==nullptr) return;
        traversal(root->left);
        vec.push_back(root->val);
        traversal(root->right);  
    }
    bool isValidBST(TreeNode* root) {
        vec.clear();
        traversal(root);
        for(int i=0;i<vec.size()-1;i++){
            if(vec[i+1]<=vec[i]) return false; 
        }
        return true;
    }
};

解法二:使用指针

class Solution {
public:
    TreeNode* pre=nullptr;
    bool isValidBST(TreeNode* root) {
        if(root==nullptr) return true;
        bool left=isValidBST(root->left);
        if(pre!=nullptr&&pre->val>=root->val) return false;
        pre=root;
        bool right=isValidBST(root->right);
        return left&&right;
    }
};

其中pre指向遍历的前一个节点。

解法三:迭代法

class Solution {
public:
    bool isValidBST(TreeNode* root) {
        if(root==nullptr) return true;
        stack<TreeNode*> st;
        st.push(root);
        TreeNode* pre=nullptr;
        while(!st.empty()){
            TreeNode* cur=st.top();
            if(cur!=nullptr){
                st.pop();
                if(cur->right) st.push(cur->right);
                st.push(cur);
                st.push(nullptr);
                if(cur->left) st.push(cur->left);
            }else{
                st.pop();
                cur=st.top();
                if(pre!=nullptr&&pre->val>=cur->val) return false;
                pre=cur;
                st.pop();
            }
        }
        return true;
    }
};
  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值