day 21:236. 二叉树的最近公共祖先;530.二叉搜索树的最小绝对差;501二叉搜索树中的众数

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

思路

在这里插入图片描述

题目中要求在二叉搜索树上任意两节点的差的绝对值的最小值。

注意是二叉搜索树,二叉搜索树可是有序的。

递归

1.数组.在一个有序数组上求两个数最小差值,把二叉搜索树转换成有序数组,然后遍历一遍数组,就统计出来最小差值了。

2.用一个pre节点记录一下cur节点的前一个节点

在这里插入图片描述


class Solution {
public:
      TreeNode* newnode=nullptr;//TreeNode* newnode=new TreeNode()不可以,传人的值为0
      int minval=INT_MAX;
      void traversal(TreeNode* root) 
      {    if(root==nullptr)return;
           traversal(root->left);
           if(newnode!=nullptr)
           {
            minval=min(minval,root->val-newnode->val);
           }
           newnode=root;
           traversal(root->right);
      }
      int getMinimumDifference(TreeNode* root)
       {
             traversal(root);
             return minval;
       }
};

中序迭代

class Solution {
public:
      
      int getMinimumDifference(TreeNode* root)
       {
           int minval=INT_MAX;
            TreeNode* node=nullptr;
           if(root==nullptr)return 0;
           stack<TreeNode*>input;
           input.push(root);
           while(!input.empty())
           {
                TreeNode* cur=input.top();
               if(cur!=nullptr)
               {
                   input.pop();
                   if(cur->right)input.push(cur->right);
                   input.push(cur);
                   input.push(nullptr);
                   if(cur->left)input.push(cur->left);
               }
               else
               {
                   input.pop();
                   cur=input.top();
                   input.pop();
                  if(node!=nullptr) minval=min(minval,cur->val-node->val);
                  node=cur;
               }
              
           }
   return minval;
       }
};

501. 二叉搜索树中的众数

思路

递归

1.对于非二叉搜索树:

采用遍历,将数存放到map里统计频率

2.对于二叉搜索树:中序遍历有顺序

1.从头中序遍历,那么一定是对相邻的两个元素作比较,然后就把出现频率最高的元素输出就可以了。
2.采用双指针,pre和cur进行比较,初始化pre=nullptr,统计当前单一元素出现频率

  if(pre==nullptr) count=1;/当前cur指向最下面的左节点,则pre指向了cur下面的空节点,所以当前元素频率计数为1else if(pre->val==cur->val) count++;
  else count=1/pre和cur数值不相等,当前值的计数又变为1

3.求最大频率的集合:一次遍历搜索树

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

if(count>maxcount)//更新maxcount
            {
                maxcount=count;
                result.clear();
                result.push_back(cur->val);
            }

代码

class Solution {
public: 
          int count=0;//统计当前元素出现计数
          int maxcount=0;//统计这个元素出现最多的数
          TreeNode* pre=nullptr;
          vector<int>result;
          void traversal(TreeNode* cur)
          {
             if(cur==nullptr)return;
             traversal(cur->left);
             if(pre==nullptr)
             {
                 count=1;//cur指向最下面的左节点,则pre指向了cur下面的空节点,所以当前元素频率计数为1;
             }
            else if(pre->val==cur->val) count++;
            else//pre和cur数值不相等,当前的值重新计数
            {
                count=1;
            }
            pre=cur;
            if(count==maxcount)result.push_back(cur->val);
            if(count>maxcount)//更新maxcount
            {
                maxcount=count;
                result.clear();
                result.push_back(cur->val);
            }
             traversal(cur->right);
          }
    vector<int> findMode(TreeNode* root) {
        traversal(root);
        return result;
        
    }
};

迭代:中序遍历的迭代法,其中间处理逻辑一点都没有变

class Solution {
public:
    vector<int> findMode(TreeNode* root) {
     int count=0;
     int maxcount=0;
     vector<int>result;
     TreeNode* pre=nullptr;
     stack<TreeNode*>input;
     if(root==nullptr)return result;
     input.push(root);
     while(!input.empty())
     {
         TreeNode* cur=input.top();
         if(cur!=nullptr)
         {
             input.pop();
             if(cur->right) input.push(cur->right);
             input.push(cur);
             input.push(nullptr);
             if(cur->left) input.push(cur->left);
         }
         else
         {
             input.pop();
             cur=input.top();
             input.pop();
             if(pre==nullptr)count=1;
             else if(pre->val==cur->val)count++;
             else count=1;
             if(count==maxcount)result.push_back(cur->val);
             if(count>maxcount)
             {
                 maxcount=count;
                 result.clear();
                 result.push_back(cur->val);
             }
             pre=cur;
         }
     }
     return result;
  }
};

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

思路:

通过后序遍历,自底向上查找
情况一:如果找到一个节点,发现左子树出现结点p,右子树出现节点q,或者 左子树出现结点q,右子树出现节点p,那么该节点就是节点p和q的最近公共祖先。
在这里插入图片描述情况二:
在这里插入图片描述情况一 和 情况二 代码实现过程都是一样的,也可以说,实现情况一的逻辑,顺便包含了情况二。

递归

1.确定递归函数返回值和参数
代码

TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q)

2.确定终止条件
遇到空的话,因为树都是空了,所以返回空。如果root等于q/p ,说明找到 q p ,则将其返回,这个返回值,后面在中节点的处理过程中会用到

if(root==nullptr)return nullptr;
if(root==p||root==q)return root;
 情况2包含在情况1里面,因为roo==q/p之间返回了。

3.单层递归逻辑和中节点的处理逻辑,

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

4.中间节点处理逻辑
1.如果left 和 right都不为空,说明此时root就是最近公共节点
2.如果left为空,right不为空,就返回right,说明目标节点是通过right返回的,反之依然。 如图,对于节点10,左子树返回为空,右子树返回7,所以节点10向上返回右子树的7

在这里插入图片描述注意:else return nullptr;//都为空,返回空,要用else,因为还有||情况

 if(left!=nullptr&&right!=nullptr)return root;//左右子树分别出现pq
        
        if(left==nullptr&&right!=nullptr) return right;//左子树为空,右不为空分别出现pq
       else if(left!=nullptr&&right==nullptr) return left;
       else return nullptr;//都为空,返回空,要用else,因为还有||情况

完整代码


class Solution {
public://后序遍历,左右中
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if(root==nullptr)return nullptr;
        if(root==p||root==q)return root; //情况2包含在情况1里面,因为roo==q/p之间返回了。
        TreeNode* left=lowestCommonAncestor(root->left,p,q);//左和右递归返回的值
        TreeNode* right=lowestCommonAncestor(root->right,p,q);
        if(left!=nullptr&&right!=nullptr)return root;//左右子树分别出现pq
        
        if(left==nullptr&&right!=nullptr) return right;//左子树为空,右不为空分别出现pq
       else if(left!=nullptr&&right==nullptr) return left;
       else return nullptr;//都为空,返回空,要用else,因为还有||情况
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值