算法训练营Day21 第六章 二叉树part7

 第一题: 530.二叉搜索树的最小绝对差 

        这道题可以使用递归法也可以使用迭代法,用双指针操作能够降低空间复杂度。代码如下:

class Solution {
private:
    int ret = INT_MAX;
    TreeNode *prev = nullptr;
    void inorder(TreeNode *curr){
        if(curr){
            inorder(curr->left);
            if(prev){
                ret = min(ret, curr->val -  prev->val);
            }
            prev = curr;
            inorder(curr->right);
        }
    }
public:
    int getMinimumDifference(TreeNode* root) {
        inorder(root);
        return ret;
    }
};

 第二题: 501.二叉搜索树中的众数 

        这道题同样可以采用双指针的思路进行解题,并且看到二叉搜索树就要立马想到它的中序遍历是有序的!!!这一点很关键!!!

        利用二叉搜索树的性质可以不利用额外的空间,否则还需要用hashmap的结构来记录出现的次数,代码如下:

class Solution {
public:
    TreeNode* prev = nullptr;
    int max_cnt = 0;
    int cur_cnt = 0;
    vector<int> result;

    void inOrder(TreeNode* node) {
        if(!node) return;
        inOrder(node->left);

        if(!prev) cur_cnt = 1; //遍历到第一个元素
        else if(node->val == prev->val) cur_cnt++;
        else cur_cnt = 1;

        prev = node; //更新上一个节点

        if (cur_cnt == max_cnt) { // 如果和最大值相同,放进result中
            result.push_back(node->val);
        }

        if (cur_cnt > max_cnt) { // 如果计数大于最大值频率
            max_cnt = cur_cnt;   // 更新最大频率
            result.clear();     // 很关键的一步,不要忘记清空result,之前result里的元素都失效了
            result.push_back(node->val);
        }

        inOrder(node->right);
    }
    
    vector<int> findMode(TreeNode* root) {
        inOrder(root);
        return result;
    }
};

 第三题: 236. 二叉树的最近公共祖先 

        这道题我先自己尝试做了一下,有一定的难度,我的想法是通过后序遍历这棵树,得到一个数组,里面存放了后序遍历的结果,然后依次判断数组中的每个节点是否是公共祖先,代码如下:

class Solution {
public:
    bool flag1 = false, flag2 = false;
    TreeNode* result = nullptr;
    vector<TreeNode*> vec;

    bool isParent(TreeNode* node, TreeNode* p, TreeNode* q) {
        if(!node) return false;
        if(node->val == p->val) flag1 = true;
        if(node->val == q->val) flag2 = true;
        isParent(node->left, p, q);
        isParent(node->right, p, q);
        return flag1 && flag2;
    }

    void postTraversal(TreeNode* node) {
        if(!node) return;
        postTraversal(node->left);
        postTraversal(node->right);
        vec.push_back(node);
    }

    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if(!root) return nullptr;
        //后序遍历(左右中)
        postTraversal(root);
        for(int i = 0; i < vec.size(); ++i) {
            if(isParent(vec[i], p, q)) return vec[i];
            flag1 = false;
            flag2 = false;
        }
        return root;
    }
};

        还可以在此基础上进行简化,同样需要采用后序遍历的方法,因为后序遍历是天然的回溯方法,通过回溯法来记录最近的公共祖先,可以从下到上来判断一棵树。代码如下:

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if(!root) return root;
        if(root == p || root == q) return root;
        TreeNode* left = lowestCommonAncestor(root->left, p, q);
        TreeNode* right = lowestCommonAncestor(root->right, p, q);
        if(left && right) return root;
        else if(!left && right) return right;
        else if(left && !right) return left;
        else return nullptr;
    }
};

        Day21打卡!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值