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

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

力扣题目链接

思路

  • 设置一个pre指针记录前一个结点

代码

1. 递归
class Solution {
public:
    int min=INT_MAX;
    TreeNode* pre=NULL;
    void inorder(TreeNode* root){
        if(root==NULL) return;
        inorder(root->left);
        if(pre!=NULL&&root->val-pre->valval-pre->val;
        }
        pre=root;
        inorder(root->right);
    }
    int getMinimumDifference(TreeNode* root) {
        inorder(root);
        return min;
    }
};
  • 时间复杂度O(n)
  • 空间复杂度O(n)
2. 非递归
class Solution {
public:
    int getMinimumDifference(TreeNode* root) {
        stack st;
        TreeNode* p=root;
        TreeNode* pre=NULL;
        int min=INT_MAX;
        while(p||!st.empty()){
            if(p){
                st.push(p);
                p=p->left;
            }
            else{
                p=st.top();st.pop();
                if(pre!=NULL&&p->val-pre->valval-pre->val;
                }
                pre=p;
                p=p->right;
            }
        }
        return min;
    }
};
  • 时间复杂度O(n)
  • 空间复杂度O(n)

501.二叉搜索树中的众数

力扣题目链接

思路

1. 普通树
  • 遍历树,用map统计频率
  • 把统计的出来的出现频率(即map中的value)排个序(把map转化数组即vector,再进行排序)
  • 取前面高频的元素
2. 二叉搜索树
  • 只遍历一遍二叉树
  • 如果频率count==maxCount(最大频率),把这个元素加入到结果集中
  • 如果频率count>maxCount的时候,不仅要更新maxCount,而且要清空结果集,再重新添加新元素

代码

1. 普通树
class Solution {
public:
    void inorder(TreeNode* root,unordered_map& map){
        if(root==NULL) return ;
        inorder(root->left,map);
        map[root->val]++;
        inorder(root->right,map); 
    }
    bool static cmp(const pair& a, const pair& b){
        return a.second>b.second;
    }
    vector findMode(TreeNode* root) {
        unordered_map map;
        //遍历树,用map统计出现频次
        inorder(root,map);
        //将map转成vetcor数组
        vector> vec(map.begin(),map.end());
        //给频率排序
        sort(vec.begin(),vec.end(),cmp);
        vector res;
        //获取频次最高的元素
        for(int i=0;i
class Solution {
public:
    unordered_map map;
    TreeNode* pre=NULL;
    void inorder(TreeNode* root,vector &res){
        if(root==NULL) return;
        inorder(root->left,res);
        if(pre!=NULL&&pre->val==root->val){
            map[pre->val]++;
        }
        pre=root;
        res.push_back(root->val);
        inorder(root->right,res);
    }
    vector findMode(TreeNode* root) {
        int max=0;
        vector maxIndex;
        vector res;
        inorder(root,res);
        bool flag=false;
        for(auto it=map.begin();it!=map.end();it++){
            if(it->second>max){
                max=it->second;
            }
            flag=true;
        }
        for(auto it=map.begin();it!=map.end();it++){
            if(it->second==max){
                maxIndex.push_back(it->first);
            }
        }
        if(flag==false) return res;
        return maxIndex;
    }
};
2. 二叉搜索树
class Solution {
public:
    int count=0,maxCount=0; //当前节点出现频率,最大频率
    TreeNode *pre=NULL;
    vector res; //存放结果集
    void traversal(TreeNode* root){
        if(root==NULL) return;
        traversal(root->left); //左
        if(pre==NULL) count=1; //第一个节点
        else if(pre->val==root->val) count++; //与前一个结点数值相同
        else count=1; //与前一个结点数值不同
        pre=root;//更新结点
        if(count==maxCount){ //当前节点出现频率与最大值相同,放入结果集
            res.push_back(root->val);
        }
        if(count>maxCount){ //当前节点
            maxCount=count;
            res.clear();
            res.push_back(root->val);
        }
        traversal(root->right);
    }
    vector findMode(TreeNode* root) {
        traversal(root);
        return res;
    }
};
  • 时间复杂度O(n)
  • 空间复杂度O(n)

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

力扣题目链接

思路

1. 递归法
  • 如果找到一个节点,发现左子树出现结点p,右子树出现节点q,或者 左子树出现结点q,右子树出现节点p,那么该节点就是节点p和q的最近公共祖先。(情况1)
  • 就是节点本身p(q),它拥有一个子孙节点q§(情况2)
  • 终止条件: 如果遇到空节点,返回null;如果遇到p或q,则将其返回
  • 单层逻辑:
  • 如果left 和 right都不为空,说明此时root就是最近公共节点
  • 如果left为空,right不为空,就返回right,说明目标节点是通过right返回的,反之依然
2. 迭代法
  • 后序非递归遍历,当访问到某结点时,栈中所有元素均为该结点的祖先结点
  • 假设先遍历到p,使用辅助数组存储其祖先元素。当遍历到q时,将当前栈中元素(q的祖先结点)与辅助数组中p的祖先结点逆序进行比较。如果遇到相同的结点,则说明是p和q的最近公共祖先。
  • 由于p和q结点被遍历到的顺序不确定,即可能是先遍历到p再遍历到q,也有可能是先q后p,因此不能简单地先将p的祖先数组放入辅助数组,而是要把先遍历到的结点的祖先结点放入辅助数组,再遇到后遍历到的结点时,弹出该结点的祖先结点与辅助数组中的元素比较。
拓展

如果递归函数有返回值,区分要搜索一条边,还是搜索整个树

搜索一条边的写法:

if (递归函数(root->left)) return ;
if (递归函数(root->right)) return ;

搜索整个树写法:

left = 递归函数(root->left);  // 左
right = 递归函数(root->right); // 右
left与right的逻辑处理;         // 中 

代码

1. 递归法
class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if(root==NULL||root==p||root==q) return root;
        //后序遍历
        TreeNode* left=lowestCommonAncestor(root->left,p,q);
        TreeNode* right=lowestCommonAncestor(root->right,p,q);
        //如果左子树为空,返回右子树;如果右子树为空,返回左子树;如果都为空,返回空
        if(left==NULL) return right;
        if(right==NULL) return left;
        //如果都不为空,返回根结点;
        return root;
    }
};
  • 时间复杂度O(n)
  • 空间复杂度O(n)
2. 迭代法
class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        TreeNode* cur=root;
        TreeNode* r=NULL;
        vector st,s;
        bool fp1=false,fp2=false;
        while(cur||!st.empty()){
            if(cur){
                st.push_back(cur);
                cur=cur->left;
            }
            else{
                cur=st[st.size()-1];
                if(cur->right&&cur->right!=r){ //如果右子树不为空且未被访问过
                    cur=cur->right;
                }
                else{
                    if(cur==p) fp1=true; //如果p被访问,置fp1=true
                    if(cur==q) fp2=true; //如果q被访问,置fp2=true
                    //当p被访问,q未被访问||当q被访问,p未被访问
                    //(当第一个结点被访问时,将其祖先元素存储到辅助数组中)
                    if(cur==p&&fp1&&!fp2||cur==q&&!fp1&&fp2){
                        for(int i=0;i=0;i--){
                            for(int j=s.size()-1;j>=0;j--){
                                if(st[i]==s[j]){
                                    return st[i];
                                }
                            }  
                        }
                    }
                    st.pop_back();
                    r=cur;
                    cur=NULL;
                }
            }
        }
        return NULL;
    }
};
  • 时间复杂度O(n)
  • 空间复杂度O(n)

你可能感兴趣的:(代码随想录刷题,算法,leetcode,数据结构)