【算法训练 day23 二叉搜索树的最小绝对差、二叉搜索树的众数、二叉树的最近公共祖先】


一、二叉搜索树的最小绝对差-LeetCode 530

Leecode链接: leetcode 977
文章链接: 代码随想录
视频链接: B站

给你一个二叉搜索树的根节点 root ,返回 树中任意两不同节点值之间的最小差值 。

示例:

输入:root = [4,2,6,1,3]
输出:1

思路

解法1:转化为数组,然后逐个计算差值,返回最小差值即可。解法2:由于题目是搜索树,所以差值最小必定出现在相邻节点,使用全局变量保存上一个节点,中间节点计算差值并保存可能的最小差值。

实现代码

递归处理

//cpp
class Solution {
public:
    TreeNode* pre = nullptr;
    int minnum = INT32_MAX;

    void test(TreeNode* root){
        if(root == nullptr) return;

        test(root->left);
        if(pre != nullptr){
            minnum = min(minnum,root->val - pre->val);
        }
        pre = root;
        test(root->right);
    }
    int getMinimumDifference(TreeNode* root) {
        test(root);
        return minnum;
    }
};

使用数组

//cpp
class Solution {
private:
vector<int> vec;
void traversal(TreeNode* root) {
    if (root == NULL) return;
    traversal(root->left);
    vec.push_back(root->val); // 将二叉搜索树转换为有序数组
    traversal(root->right);
}
public:
    int getMinimumDifference(TreeNode* root) {
        vec.clear();
        traversal(root);
        if (vec.size() < 2) return 0;
        int result = INT_MAX;
        for (int i = 1; i < vec.size(); i++) { // 统计有序数组的最小差值
            result = min(result, vec[i] - vec[i-1]);
        }
        return result;
    }
};

个人问题

对于使用双指针还不够熟练。


二、二叉搜索树的众数-LeetCode 501

Leecode链接: LeetCode 501
文章链接: 代码随想录
视频链接: B站

给你一个含重复值的二叉搜索树(BST)的根节点 root ,找出并返回 BST 中的所有 众数(即,出现频率最高的元素)。

如果树中有不止一个众数,可以按 任意顺序 返回。

示例:

输入:root = [1,null,2,2]
输出:[2]

思路

两种解法:1.中序遍历形成map数组,然后对数组进行排序,可得众数。2.递归过程中计算众数,使用一个计数器,每遇到相同的值count加1,遇到不同的值count恢复为1,然后使用maxcount记录可能成为众数出现的频率。遍历完整个树为止。

实现代码

map统计计数

//cpp
class Solution {
private:

void searchBST(TreeNode* cur, unordered_map<int, int>& map) { // 前序遍历
    if (cur == NULL) return ;
    map[cur->val]++; // 统计元素频率
    searchBST(cur->left, map);
    searchBST(cur->right, map);
    return ;
}
bool static cmp (const pair<int, int>& a, const pair<int, int>& b) {
    return a.second > b.second;
}
public:
    vector<int> findMode(TreeNode* root) {
        unordered_map<int, int> map; // key:元素,value:出现频率
        vector<int> result;
        if (root == NULL) return result;
        searchBST(root, map);
        vector<pair<int, int>> vec(map.begin(), map.end());
        sort(vec.begin(), vec.end(), cmp); // 给频率排个序
        result.push_back(vec[0].first);
        for (int i = 1; i < vec.size(); i++) {
            // 取最高的放到result数组中
            if (vec[i].second == vec[0].second) result.push_back(vec[i].first);
            else break;
        }
        return result;
    }
};

递归过程中计数

//cpp
class Solution {
public:
    int count = 0;
    int maxcount = 0;
    vector<int> res;
    TreeNode* pre = nullptr;
    void test(TreeNode* root){
        if(root == nullptr){
            return;
        }

        test(root->left);
        if(pre == nullptr){
            count = 1;
        }
        else if(root->val == pre->val){
            count++;
        }
        else{
            count = 1;
        }
        
        if(count>maxcount){
            maxcount = count;
            res.clear();
            res.push_back(root->val);
        }
        else if(count == maxcount){
            res.push_back(root->val);
        }
        pre = root;

        test(root->right);
        return;
    }
    vector<int> findMode(TreeNode* root) {
        res.clear();
        test(root);
        return res;
    }
};

个人问题

在实现代码时,maxcount的更新位置写在了root->val != pre->val的条件分支中,导致没有存储真正的众数;count初始值最初个人设置为1,但在执行时出现访问未定义行为,原因在于count初始值手动设置为1,但pre初始值也为1,导致不能访问正确的第一个元素的值。


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

Leecode链接: LeetCode 236
文章链接: 代码随想录
视频链接: B站

给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

示例:

输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
输出:3
解释:节点 5 和节点 1 的最近公共祖先是节点 3

思路

使用后序遍历,考虑一个一般情况,两个节点为某个父节点的左右子树,如果找到了该节点左右子树的递归函数就返回该节点的指针给父节点的这一层函数,这一层根据返回结果返回对应指针,如果都存在,表明要找的节点就在该父节点的孩子节点中,返回父节点自身即可。考虑一个特殊情况,如果两个节点互为父子节点,这时直接返回最先遇到的节点指针即可,如果一侧为空返回另一侧不为空的节点指针。

实现代码

//cpp
class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
    	if(root == NULL) return NULL;
        if(root->val==p->val||root->val==q->val)return root;

        TreeNode* left_p = lowestCommonAncestor(root->left,p,q);

        TreeNode* right_p = lowestCommonAncestor(root->right,p,q);

        if(left_p&&right_p)return root;
        else if(!left_p&&right_p) return right_p;
        else if(left_p&&!right_p) return left_p;

        else return NULL;
    }
};

个人问题

代码没有自己写出来。

总结

本题比较巧妙,对各个情况处理比较特殊。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值