首页 > 编程语言 >代码随想录算法训练营第二十一天| 530.二叉搜索树的最小绝对差 501.二叉搜索树中的众数 236. 二叉树的最近公共祖先

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

时间:2023-08-21 16:44:06浏览次数:45  
标签:pre TreeNode cur 随想录 二叉 搜索 result NULL 节点

 

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

    卡哥建议:需要领悟一下二叉树遍历上双指针操作,优先掌握递归 

    题目链接/文章讲解:https://programmercarl.com/0530.%E4%BA%8C%E5%8F%89%E6%90%9C%E7%B4%A2%E6%A0%91%E7%9A%84%E6%9C%80%E5%B0%8F%E7%BB%9D%E5%AF%B9%E5%B7%AE.html

    视频讲解:https://www.bilibili.com/video/BV1DD4y11779

    做题思路:

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

    遇到在二叉搜索树上求什么最值啊,差值之类的,最直观的想法,就是把二叉搜索树转换成有序数组,然后遍历一遍数组,就统计出来最小差值了。

    双指针法需要用一个pre节点记录一下cur节点的前一个节点。比如,一开始,cur是根节点,pre是空节点,中序遍历的话,cur->left,cur会指向左子树,这时候就需要用pre = cur,来保存住cur指向的左孩子节点,也就是前一个遍历过的节点,看卡哥文章的图。

     本题代码:

 1 class Solution {
 2 private:
 3 int result = INT_MAX;
 4 TreeNode* pre = NULL;
 5 void traversal(TreeNode* cur) {
 6     if (cur == NULL) return;
 7     traversal(cur->left);   // 左
 8     if (pre != NULL){       // 中
 9         result = min(result, cur->val - pre->val);
10     }
11     pre = cur; // 记录前一个
12     traversal(cur->right);  // 右
13 }
14 public:
15     int getMinimumDifference(TreeNode* root) {
16         traversal(root);
17         return result;
18     }
19 };

 

 501.二叉搜索树中的众数 

     卡哥建议:和 530差不多双指针思路,不过 这里涉及到一个很巧妙的代码技巧。可以先自己做做看,然后看我的视频讲解。

https://programmercarl.com/0501.%E4%BA%8C%E5%8F%89%E6%90%9C%E7%B4%A2%E6%A0%91%E4%B8%AD%E7%9A%84%E4%BC%97%E6%95%B0.html

    视频讲解:https://www.bilibili.com/video/BV1fD4y117gp

    做题思路:

    既然是搜索树,它中序遍历就是有序的。遍历有序数组的元素出现频率,从头遍历,那么一定是相邻两个元素作比较,然后就把出现频率最高的元素输出就可以了。

    双指针法:弄一个指针指向前一个节点,这样每次cur(当前节点)才能和pre(前一个节点)作比较。而且初始化的时候pre = NULL,这样当pre为NULL时候,我们就知道这是比较的第一个元素。因为此时cur是当前比较的第一个元素,没有前一个。

    题目要求最大频率的元素集合(注意是集合,不是一个元素,可以有多个众数),如果是数组上应该是先遍历一遍数组,找出最大频率(maxCount),然后再重新遍历一遍数组把出现频率为maxCount的元素放进集合。(因为众数有多个)这种方式遍历了两遍数组。那么我们遍历两遍二叉搜索树,把众数集合算出来也是可以的。但这里其实只需要遍历一次就可以找到所有的众数。

   如果 频率count 等于 maxCount(最大频率),当然要把这个元素加入到结果集中;

   如果频率count 大于 maxCount的时候,不仅要更新maxCount,而且要清空结果集,因为结果集之前的元素都失效了。

   本题代码:

 1 class Solution {
 2 private:
 3     int maxCount = 0; // 最大频率
 4     int count = 0; // 统计频率
 5     TreeNode* pre = NULL;
 6     vector<int> result;
 7     void searchBST(TreeNode* cur) {
 8         if (cur == NULL) return ;
 9 
10         searchBST(cur->left);       // 左
11                                     // 中
12         if (pre == NULL) { // 第一个节点
13             count = 1;
14         } else if (pre->val == cur->val) { // 与前一个节点数值相同
15             count++;
16         } else { // 与前一个节点数值不同
17             count = 1;
18         }
19         pre = cur; // 更新上一个节点
20 
21         if (count == maxCount) { // 如果和最大值相同,放进result中
22             result.push_back(cur->val);
23         }
24 
25         if (count > maxCount) { // 如果计数大于最大值频率
26             maxCount = count;   // 更新最大频率
27             result.clear();     // 很关键的一步,不要忘记清空result,之前result里的元素都失效了
28             result.push_back(cur->val);
29         }
30 
31         searchBST(cur->right);      // 右
32         return ;
33     }
34 
35 public:
36     vector<int> findMode(TreeNode* root) {
37         count = 0;
38         maxCount = 0;
39         TreeNode* pre = NULL; // 记录前一个节点
40         result.clear();
41 
42         searchBST(root);
43         return result;
44     }
45 };

 

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

   卡哥建议:本题其实是比较难的,可以先看我的视频讲解 

https://programmercarl.com/0236.%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E6%9C%80%E8%BF%91%E5%85%AC%E5%85%B1%E7%A5%96%E5%85%88.html

   视频讲解:https://www.bilibili.com/video/BV1jd4y1B7E2

   做题思路:

   如何判断一个节点是节点q和节点p的公共祖先呢。

   首先最容易想到的一个情况:如果找到一个节点,发现左子树出现结点p,右子树出现节点q,或者 左子树出现结点q,右子树出现节点p,那么该节点就是节点p和q的最近公共祖先。 即情况一:

   判断逻辑是 如果递归遍历遇到q,就将q返回,遇到p 就将p返回,那么如果 左右子树的返回值都不为空,说明此时的中节点,一定是q 和p 的最近祖先。

    但是很多人容易忽略一个情况,就是节点本身p(q),它拥有一个子孙节点q(p)。 情况二:

   其实情况一 和 情况二 代码实现过程都是一样的,也可以说,实现情况一的逻辑,顺便包含了情况二。因为遇到 q 或者 p 就返回,这样也包含了 q 或者 p 本身就是 公共祖先的情况。

 

   本题代码:

 1 TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
 2         if (root == q || root == p || root == NULL) return root;
 3         TreeNode* left = lowestCommonAncestor(root->left, p, q);
 4         TreeNode* right = lowestCommonAncestor(root->right, p, q);
 5         if (left != NULL && right != NULL) return root;
 6 
 7         if (left == NULL && right != NULL) return right;
 8         else if (left != NULL && right == NULL) return left;
 9         else  { //  (left == NULL && right == NULL)
10             return NULL;
11         }
12 
13     }

 

 

标签:pre,TreeNode,cur,随想录,二叉,搜索,result,NULL,节点
From: https://www.cnblogs.com/romantichuaner/p/17637076.html

相关文章

  • 代码随想录算法训练营第二十天| 654.最大二叉树 617.合并二叉树 700.二叉搜索树
      654.最大二叉树    卡哥建议:又是构造二叉树,昨天大家刚刚做完 中序后序确定二叉树,今天做这个 应该会容易一些, 先看视频,好好体会一下 为什么构造二叉树都是 前序遍历    题目链接/文章讲解:https://programmercarl.com/0654.%E6%9C%80%E5%A4%A7%E4%BA%8C%E5......
  • 【二叉树前沿篇】树
    1树的概念树是一种非线性的数据结构,它是由n(n>=0)个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。树有一个特殊的结点,称为根结点,根节点没有前驱结点。除根节点外,其余结点被分成M(M>0)个互不相交的集合T1、T2、……......
  • 标签大全(纯文字版) 如需搜索使用Ctrl+F
    【公司信息】全部页面可用公司名称------{co('name')}公司地址------{co('address')}邮政编码------{co('postcode')} 联系人------{co('contact')} 联系手机------{co('phone')} 联系电话------{co('tel')} ......
  • 深入了解Elasticsearch搜索引擎篇:倒排索引、架构设计与优化策略
    什么是倒排索引?有什么好处?倒排索引是一种用于快速检索的数据结构,常用于搜索引擎和数据库中。与传统的正排索引不同,倒排索引是根据关键词来建立索引,而不是根据文档ID。倒排索引的建立过程如下:首先,将每个文档拆分成一系列的关键词或词项,然后建立一个词项到文档的映射。对每个关键......
  • #yyds干货盘点# LeetCode程序员面试金典:完全二叉树的节点个数
    题目:给你一棵 完全二叉树 的根节点 root ,求出该树的节点个数。完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2h 个节点。 示例1:输入:r......
  • 验证二叉搜索树
    98.验证二叉搜索树-力扣(LeetCode)二叉搜索树:根节点的左子树的所有元素的值都小于根节点,根节点右子树的所有元素都大于根节点的值。使用中序遍历的序列一定是一个递增的序列,因此一个二叉树如果中序遍历之后得到的是一个递增序列那么它一定是二叉搜索树。 ......
  • 二叉搜索树中的搜索
    700.二叉搜索树中的搜索-力扣(LeetCode)经验1:情况要考虑周全,开始只想到了找到的情况,而没有去想没找到的情况,漏掉了if(root==nullptr)returnroot;经验2:如果该层想要下一层的返回结果,则在该层定义一个返回值类型的变量,然后在该层接递归的返回值......
  • 解密Nginx与Elasticsearch的协同高效:深入理解反向代理与全文搜索
    在当今高度互联的网络环境中,后端技术的结合与优化对于构建高性能应用至关重要。本篇博客将聚焦于两个关键主题:Nginx反向代理和Elasticsearch全文搜索,通过深入分析实现原理和代码示例,展示它们如何协同工作以提升系统性能。Nginx反向代理的作用Nginx不仅仅是一款高性能的Web服务器,还......
  • 深入探索Elasticsearch的分布式搜索与性能优化
    在后端开发领域,Elasticsearch作为一款强大的分布式搜索与分析引擎,被广泛应用于构建高性能的搜索和数据分析系统。本文将深入探讨Elasticsearch的分布式特性、搜索原理以及性能优化策略。通过结合实际代码示例,为读者提供关于Elasticsearch的深奥知识和实用方法。1.Elasticsearch概......
  • 微信小程序(8)搜索页以及历史记录管理
    1.效果1.逻辑界面初始化调接口获取两部分数据:1.搜索框默认的搜索placeholder:下面自由自在...2.热搜榜数据:前20条热搜数据3.获取本地存的历史搜索记录historyList搜索框输入文字事件:1.调用接口根据关键字搜索音乐2.判断搜索记录是否有对应关键字,如果有就将......