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

今天是二叉树学习的第六天。主要的学习内容有:二叉搜索树相关题目,以及找出二叉树中任意两点的公共祖先问题。

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

题目链接:530. 二叉搜索树的最小绝对差 - 力扣(LeetCode)

这个题的背景是二叉搜索树,所以一定是使用中序遍历完成。题目求解的是任意两个节点的最小绝对差,由于中序遍历的二叉搜索树是单调递增的,我们可以沿用双指针的方法,并且对最小绝对差进行一个动态的更新。具体代码实现如下:
 

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
 class Solution {
public:
TreeNode* pre=NULL;
int min=100010;
    void order(TreeNode* root)
    {
        if(root==NULL) return;
        order(root->left);
        if(pre!=NULL&&root->val-pre->val<min) min=root->val-pre->val;
        pre=root;
        order(root->right);
    }
    int getMinimumDifference(TreeNode* root) {
        order(root);
        return min;

    }
};

使用迭代法也是类似的思想,具体代码实现如下:
 


/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    int getMinimumDifference(TreeNode* root) {
        stack<TreeNode*> st;
        TreeNode* pre=NULL;
        TreeNode* cur=root;
        int min=100010;
        while(cur!=NULL||!st.empty())
        {
            if(cur!=NULL)
            {
                st.push(cur);
                cur=cur->left;
            }
            else
            {
                cur=st.top();
                st.pop();
                if(pre!=NULL&&cur->val-pre->val<min) min=cur->val-pre->val;
                pre=cur;
                cur=cur->right;
            }
        }
        return min;
    }
};

501.二叉搜索树中的众数

题目链接:501. 二叉搜索树中的众数 - 力扣(LeetCode)

我拿到这个题目的思路是用map去记录二叉搜索树的所有数值以及出现次数,将这个map设置成一个vector,然后手写一个快速排序,根据每个数值出现的次数从大到小排序并输出。具体代码如下:
 

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    void order(TreeNode* root,unordered_map<int,int> &map)
    {
        if(root==NULL) return;
        order(root->left,map);
        map[root->val]++;
        order(root->right,map);
    }
    void quick_sort(vector<pair<int,int>> &result,int l,int r)
    {
        if(l>=r) return;
        int i=l-1;
        int j=r+1;
        int k=l+r>>1;
        int mid=result[k].second;
        while(j>i)
        {
            do i++;while(result[i].second>mid);
            do j--;while(result[j].second<mid);
            if(j>i) swap(result[i],result[j]);
        }
        quick_sort(result,l,k);
        quick_sort(result,k+1,r);
    }
    vector<int> findMode(TreeNode* root) {
        unordered_map<int,int> map;
        order(root,map);
        vector<pair<int,int>> result(map.begin(),map.end());
        quick_sort(result,0,result.size()-1);
        vector<int> s;
        s.push_back(result[0].first);
        for(int i=1;i<result.size();i++)
        {
            if(result[i].second==result[0].second) s.push_back(result[i].first);
        }
        return s;
    }
};

后来参考了随想录的题解,通过递归维护一个count和max_count,并根据根节点进行更新。挺巧妙的。具体代码实现如下:
 

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
vector<int> result;
int max_count=1;
int count=0;
TreeNode* pre=NULL;
    void order(TreeNode* root)
    {
        if(root==NULL) return;
        order(root->left);
        if(pre!=NULL&&pre->val==root->val) count++;
        else if(pre==NULL) 
        {
            count++;
        }
        else{
            count=1;
        }
        pre=root;
        if(count==max_count) result.push_back(root->val);
        if(count>max_count)
        {
            max_count=count;
            result.clear();
            result.push_back(root->val);
        }
        order(root->right);

    }
    vector<int> findMode(TreeNode* root) {
        order(root);
        return result;
    }
};

使用迭代法也是一样的思路。具体代码实现如下:
 

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<int> findMode(TreeNode* root) {
        vector<int> result;
        stack<TreeNode*> st;
        TreeNode* cur=root;
        TreeNode* pre=NULL;
        int count=0;
        int max_count=1;
        while(cur!=NULL||!st.empty())
        {
            if(cur!=NULL)
            {
                st.push(cur);
                cur=cur->left;
            }
            else
            {
                cur=st.top();
                st.pop();
                if(pre!=NULL&&pre->val==cur->val) count++;
                else if(pre==NULL) count++;
                else count=1;
                pre=cur;
                if(count==max_count) result.push_back(cur->val);
                if(count>max_count)
                {
                    result.clear();
                    max_count=count;
                    result.push_back(cur->val);
                }
                cur=cur->right;
            }
        }
         return result;
    }
};

236. 二叉树的最近公共祖先
题目链接:236. 二叉树的最近公共祖先 - 力扣(LeetCode)

我自己的实现方法是,通过递归和回溯得到根节点到目标节点的路径,然后将两条路径从后往前遍历,找到第一个相同的节点就是他们的公共祖先。具体代码实现如下:
 

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    void order(TreeNode* root,vector<TreeNode*> &vec,TreeNode* p,vector<TreeNode*>& result)
    {
        vec.push_back(root);
        if(root==NULL) return;
        if(root==p)
        {
           result=vec;
        }
        if(root->left!=NULL)
        {
            order(root->left,vec,p,result);
            vec.pop_back();
        }
        if(root->right!=NULL)
        {
             order(root->right,vec,p,result);
             vec.pop_back();
        }       
    }
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        vector<TreeNode*> result1;
        vector<TreeNode*> result2;
        vector<TreeNode*> vec;
        order(root,vec,p,result1);
        vec.clear();
        order(root,vec,q,result2);
        for(int i=result1.size()-1;i>=0;i--)
        {
            for(int j=result2.size()-1;j>=0;j--)
            {
                if(result1[i]==result2[j])
                {
                    return result1[i];
                }
            }
        }
        return root;
    }
};

然后参考了一下随想录的题解。随想录的做法是通过后续遍历,如果存在p或q就直接返回该节点,如果某节点的左子树和右子树都不为空,说明该节点为目标节点的公共祖先。将该节点层层返回即可得到答案。确实感觉自己想的话想不到这样的做法。具体代码实现如下:
 

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if(root==NULL) return NULL;
        if(root==p||root==q) return root;
        TreeNode* left=lowestCommonAncestor(root->left,p,q);
        TreeNode* right=lowestCommonAncestor(root->right,p,q);
        if(left!=NULL&&right!=NULL) return root;
        else if(left==NULL&&right!=NULL) return right;
        else if(left!=NULL&&right==NULL) return left;
        else return NULL;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值