代码随想Day21 | 530.二叉搜索树的最小绝对差、501.二叉搜索树中的众数、236. 二叉树的最近公共祖先

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

这道题和验证二叉搜索树思路几乎相同,因为二叉搜索树的特殊,最小绝对差一定是在中序遍历的相邻两个节点之间,因此需要把上一个节点保存下来,然后进行计算,使用的遍历方式是中序遍历,具体细节不再赘述,详细代码如下:

class Solution {
public:
    TreeNode* pre = nullptr;
    int min_res = INT_MAX;
    void dfs(TreeNode* root)
    {
        if(root==nullptr) return ;
        dfs(root->left);//左
        //中
        if(pre!=nullptr)
        {
            min_res = min(min_res,root->val-pre->val);
        }
        pre = root; //保存前一节点
        dfs(root->right);
    }
    int getMinimumDifference(TreeNode* root) {
        dfs(root);
        return min_res;
    }
};

501. 二叉搜索树中的众数

这道题目中有强调众数可能不止一个,所以我的思路是统计每个节点val的个数,同时维护一个出现最高的频率,把每个节点出现的次数保存在哈希表中, 最后再遍历哈希表,value==最高频率的节点放入结果vector中,详细代码如下:

写代码时犯了一个语法错误:在遍历哈希表的时候,取迭代器中对应的元素不需要用指针,直接it->first就可

class Solution {
public:
    //TreeNode* pre = nullptr;
    unordered_map map;
    int count=0;
    void dfs(TreeNode* root)
    {
        if(root==nullptr) return ;
        dfs(root->left);
        //中
        map[root->val]++;
        count = max(count, map[root->val]);
        dfs(root->right);
    }
    vector findMode(TreeNode* root) {
        if(root==nullptr) return {};
        vector res;
        dfs(root);
        for(unordered_map::iterator it = map.begin();it!=map.end();it++)
        {
            if(it->second==count) res.push_back(it->first);
        }
        return res;

    }
};

但是我的思路没有用到二叉搜索树的性质,用到二叉搜索树的性质则不需要额外的空间,且一遍就可以得到众数,思路比较巧妙:

弄一个指针指向前一个节点,这样每次cur(当前节点)才能和pre(前一个节点)作比较。

而且初始化的时候pre = NULL,这样当pre为NULL时候,我们就知道这是比较的第一个元素。

代码如下:

if (pre == NULL) { // 第一个节点
    count = 1; // 频率为1
} else if (pre->val == cur->val) { // 与前一个节点数值相同
    count++;
} else { // 与前一个节点数值不同
    count = 1;
}
pre = cur; // 更新上一个节点

因为要求最大频率的元素集合(注意是集合,不是一个元素,可以有多个众数),如果是数组上大家一般怎么办?其实只需要遍历一次就可以找到所有的众数。

如果 频率count 等于 maxCount(最大频率),当然要把这个元素加入到结果集中(以下代码为result数组),代码如下:

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

是不是感觉这里有问题,result怎么能轻易就把元素放进去了呢,万一,这个maxCount此时还不是真正最大频率呢。

所以下面要做如下操作:

频率count 大于 maxCount的时候,不仅要更新maxCount,而且要清空结果集(以下代码为result数组),因为结果集之前的元素都失效了。

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

最终详细代码如下:

class Solution {
public:
    TreeNode* pre =nullptr;
    int max_count = 0;
    int count = 0;
    vector res;
    void dfs(TreeNode* root)
    {
        if(root==nullptr) return ;
        dfs(root->left);
        //中
        if(pre==nullptr) count=1;
        else if(pre->val==root->val) count++;
        else count=1; //值不相等

        if(count==max_count) res.push_back(root->val); //相同出现的频率次数可以添加

        else if(count>max_count) //出现频率更高的数
        {
            max_count = count;
            res.clear(); //清空数组,前面的都是都不是众数
            res.push_back(root->val);
        }
        pre = root; //更新pre
        dfs(root->right);
    }

    vector findMode(TreeNode* root) {
        dfs(root);
        return res;
    }
};

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

这道题目使用后序遍历来解决,代码看起来比较简洁,但涉及到的细节思想比较多,看代码随想录消化,后面还需巩固,详细代码如下:

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

你可能感兴趣的:(好好刷leetcode,深度优先,算法)