代码随想录算法训练营第二十一天 | 530.二叉搜索树的最小绝对差,501.二叉搜索树中的众数,236. 二叉树的最近公共祖先

目录

530.二叉搜索树的最小绝对差

思路与代码实现

501.二叉搜索树中的众数

思路与代码实现

236. 二叉树的最近公共祖先

 思路与代码实现


530.二叉搜索树的最小绝对差

题目链接:530. 二叉搜索树的最小绝对差

思路与代码实现

本来看成了二叉树,没啥思路;但发现是二叉搜索树,二叉搜索树中,与某结点绝对差最小的是左子树最右结点或右子树最左结点,我的思路是每次求出该结点左子树的最右值与右子树的最左值,与最小绝对差进行比较,最终得出结果:

class Solution {
public:
    int minimum = INT_MAX;
    void minDifference(TreeNode* cur){
        if(cur == NULL)    return;
        if(cur->left){
            TreeNode* leftMax = cur->left;
            while(leftMax->right){
                leftMax = leftMax->right;
            }
            minimum = min(minimum, cur->val - leftMax->val);
            minDifference(cur->left);
        }
        if(cur->right){
            TreeNode* rightMin = cur->right;
            while(rightMin->left){
                rightMin = rightMin->left;
            }
            minimum = min(minimum, rightMin->val - cur->val);
            minDifference(cur->right);
        }
    }
    int getMinimumDifference(TreeNode* root) {
        minDifference(root);
        return minimum;
    }
};

但是查看解析后发现,常规思路是先把二叉搜索树的值从小到大排好,再相邻数之间求差得出结果;写了也有一些二叉树的代码了,现在感觉迭代法和递归法完全就是一个东西,只不过迭代是用栈模拟递归的逻辑,以后我就只写其中一种代码了,毕竟都是一个意思。

class Solution {
public:
    vector vec;
    void traversal(TreeNode* cur){
        if(cur == NULL) return;
        if(cur->left)   traversal(cur->left);
        vec.push_back(cur->val);
        if(cur->right)  traversal(cur->right);
    }
    int getMinimumDifference(TreeNode* root) {
        traversal(root);
        int minmum = INT_MAX;
        for(int i = 1; i < vec.size(); ++i){
            minmum = min(minmum, vec[i] - vec[i-1]);
        }
        return minmum;
    }
};

结果就是,第一种我的思路,因为每次都要去找左右子树的最大最小值,时间占用较高,但是空间占用较少;第二种常规思路,时间占用较少,不过空间相对高一点;不过这好像并不重要。

501.二叉搜索树中的众数

题目链接:501. 二叉搜索树中的众数

思路与代码实现

第一思路是用哈希表来存储二叉树结点的频率,但是由于是二叉搜索树,可以直接根据逻辑相邻结点的关系来求解;

class Solution {
public:
    int countMax = 0;
    int count = 0;
    vector result;
    TreeNode* pre = NULL;
    void traversal(TreeNode* cur){
        if(cur == NULL) return;
        traversal(cur->left);
        if(pre == NULL || pre->val != cur->val) count = 1;
        else if(pre->val == cur->val)   ++count;
        pre = cur;
        if(count == countMax){
            result.push_back(cur->val);
        } else if(count > countMax){
            countMax = count;
            result.clear();
            result.push_back(cur->val);
        }
        traversal(cur->right);
    }
    vector findMode(TreeNode* root) {
        traversal(root);
        return result;
    }
};

236. 二叉树的最近公共祖先

题目链接:236. 二叉树的最近公共祖先

 思路与代码实现

自己看没思路,查看解析后豁然开朗。还记得之前我们记过这么一句话:

当需要收集孩子信息向上一层返回的时候,选择后序遍历。

本题中找公共祖先,从底向上寻找肯定要更加方便,而二叉树回溯的过程就是从底向上。后序遍历是天然的回溯过程,所以本题采用后序遍历。

若一个结点出现在当前结点的左子树,另一个在右子树,则说明当前结点就是最近公共祖先,这种情况只需要遍历左右子树,若有结点,则返回结点,否则返回空;还有一种情况,即其中一个结点是另一个结点的子孙,这种情况父结点即为公共祖先。

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

你可能感兴趣的:(算法,数据结构,leetcode,c++)