代码随想录第21天 | 二叉搜索树的最小绝对差、二叉搜索树中的众数 、二叉树的最近公共祖先

一、前言

参考文献:代码随想录

今天还是二叉树,刷的是新知识,主要涉及到二叉树的双指针遍历操作。话不多说,直接开始吧!

二、二叉搜索树的最小绝对差

1、思路一:

最原始的思路就是中序遍历搜索二叉树,出来的自然就是一个由小到大的数组,只要比较两个数组之间的值,找出最小的绝对值即可。(此方法会造成O(n)的空间复杂度)

2、代码一:

class Solution {
private:
    vector<int> res;
    void getMinAbs(TreeNode* root) {
        // 中序遍历出来就是一个升序数组
        if (root == NULL) return;
        getMinAbs(root->left);
        res.push_back(root->val);
        getMinAbs(root->right);
    }
public:
    int getMinimumDifference(TreeNode* root) {
        int minAbs = INT_MAX;
        getMinAbs(root);
        // 只要敝比较两个相邻的元素,就可以找到
        for (int i = 0; i < res.size() - 1; i++) {
            if ((res[i + 1] - res[i]) < minAbs) {
                minAbs = (res[i + 1] - res[i]);
            }
        }

        return minAbs;
    }
};

3、思路二:

这个思路很巧妙,利用的是二叉树上的双指针,来达到此效果。

(1)一个pre指针一个cur指针,pre指针一直指向cur的前一个节点,这实现起来在代码中很巧妙。

(2)一直遍历,一直比较就ok了。

4、代码二:

class Solution {
private:
    int result = INT_MAX;
    TreeNode* pre;
    void getMinAbs(TreeNode* cur) {
        if (cur == NULL) return;
        getMinAbs(cur->left);
        if (pre != NULL) {
            result = min(result, abs(cur->val - pre->val));
        }
        pre = cur;
        getMinAbs(cur->right);
    }
public:
    int getMinimumDifference(TreeNode* root) {
        getMinAbs(root);
        return result;
    }
};

三、二叉搜索树中的众数

1、思路:

我的第一思路就是递归-统计,找出最大的数,就结束了。

代码如下:

class Solution {
private:   
    map<int, int> my_map;
    void getMap(TreeNode* root) {
        if (root == NULL) return;
        getMap(root->left);
        my_map[root->val]++;
        getMap(root->right);
    }

public:
    vector<int> findMode(TreeNode* root) {
        int max = INT_MIN;
        getMap(root);
        for (auto it = my_map.begin(); it != my_map.end(); it++) {
            if (max < it->second) max = it->second;
        }
        vector<int> result;
        for (auto it = my_map.begin(); it != my_map.end(); it++) {
            if (max == it->second) result.push_back(it->first);
        }
        return result;
    }
};

思路二的操作很华丽,也很实用,主要是利用双指针不断维护最大值和统计数以及返回的数组。

总结了以下节点:

(1)创建一个统计和最大的数值,全局变量

(2)利用中序遍历,在中的时候做和第一题差不多的逻辑,并且多加一些功能。

(3)遍历完就可以返回数组了。

2、代码如下:

class Solution {
private:
    int count = 0;
    int maxcount = 0;
    vector<int> result;
    TreeNode* pre;
    void getResult(TreeNode* cur) {
        if (cur == NULL) return;
        getResult(cur->left); // 左
        // 中
        if (pre == NULL) {
            count = 1;
        } else if (pre->val == cur->val) { // 相等就添加累加值
            count++;
        } else { // 不相等就刷新
            count = 1;
        } 
        pre = cur;
        if (count == maxcount) {
            result.push_back(cur->val);
        }
        if (count > maxcount) { // 累加大于max,就刷新result
            maxcount = count;
            result.clear();
            result.push_back(cur->val);
        }
        // 右
        getResult(cur->right);
    }
public:
    vector<int> findMode(TreeNode* root) {
        getResult(root);
        return result;
    }
};

四、二叉树最近的公共祖先

1、思路:

这个题目首先得了解什么最近公共祖先:

百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

举个例子

如果pq使6,5那么7就是公共祖先。

代码的逻辑就是:

后序遍历,左边遍历出p的话就往上返回,一直返回到根节点,返回结果。

比如遍历到10了左为空,有不为空,那就返回右边。

还有一个小的细节,例如p为7,q为5,那么7就是最近祖先,为什么呢?一旦遍历到7,就往上返回了,那么q怎么办?其实这个时候已经知道了q要么在下面,要么在右边,如果是在右边的话,那就是逻辑1了。

2、代码如下,好好体会:

class Solution {
private:
    TreeNode* findPQ(TreeNode* root, TreeNode* p, TreeNode* q) {
        if (root == NULL) return NULL;
        if (root == p || root == q) return root;
        // 左
        TreeNode* left = findPQ(root->left, p, q);
        // 右
        TreeNode* right = findPQ(root->right, p, q);
        // 中
        if (left != NULL && right != NULL) return root;
        else if (left != NULL && right == NULL) return left;
        else if (left == NULL && right != NULL) return right;
        else return NULL;
    }
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        return findPQ(root, p, q);
    }
};

 学习时间:2小时

leave message:

He who draws noble delights from sentimets of portry is a true poet, though he never written a line in all his life.

从诗歌情感中汲取高尚快乐的人是真正的诗人,虽然他从未写过诗。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值