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

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

时间:2024-06-02 22:43:38浏览次数:33  
标签:count 遍历 TreeNode cur 随想录 nullptr 二叉 搜索 root

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

题目链接 文章讲解 视频讲解
关键词: 二叉搜索树 --> 中序遍历

关于递归的返回值
  由于需要遍历整棵二叉树,所以返回值为void,如果不是遍历整棵二叉树,需要在得到结果时立即返回结果,此时返回值才不为空

怎样使用两个指针pre和cur使得pre始终指向cur的前一个节点?

  • 中序搜索,cur指向的第一个节点是左子树最左边的节点,而cur的前一个节点是nullptr,所以pre应初始化为nullptr
  • 回溯时(中序处理时)cur要指向下一个节点,所以应该在cur指向下一个节点前(进行下一层递归前)将pre指向cur当前的位置
class Solution {
private:
    int minValue = INT_MAX;
    TreeNode* pre = nullptr;
public:
    int getMinimumDifference(TreeNode* root) {
        traversal(root);
        return minValue;
    }

    // 二叉搜索树,中序遍历保持顺序
    void traversal(TreeNode* cur) {
        if(cur == nullptr) return ;
        // 中序遍历左子树
        traversal(cur->left);
        // 保存最小值
        if(pre) minValue = min(minValue, cur->val - pre->val);
        // 回溯前保存cur的值保证pre始终指向cur的前一个节点
        pre = cur;
        // 中序遍历右子树
        traversal(cur->right);
    }
};

501.二叉搜索树中的众数

题目链接 文章讲解 视频讲解

方法一 哈希表

需要遍历两次

思路:中序遍历二叉搜索树,用map记录每个数字出现的频率,并记录最高频率
   遍历map将频率最高的数字保存在结果集中

class Solution {
private:
    // 记录最高频率
    int count = 0;
public:
    vector<int> findMode(TreeNode* root) {
        vector<int> ans;
        unordered_map<int, int> map;
        traversal(root, map);
        // 遍历map,如果频率是最高的,则将结果保存在结果集中
        for(auto pair : map) {
            if(pair.second == count) ans.push_back(pair.first);
        }
        return ans;
    }

    void traversal(TreeNode* node, unordered_map<int, int>& map) {
        if(node == nullptr) return ;
        // 中序遍历左子树            
        traversal(node->left, map);
        // 使用哈希表保存每个数出现的频率
        map[node->val]++;
        // 更新最高频率
        count = max(count, map[node->val]);

        // 中序遍历右子树
        traversal(node->right, map);
    }
};

方法二 双指针

只需遍历一遍

trick: 遍历的同时将满足要求的数加入结果集,如果最高频率发生变化时,则清空结果集重新添加满足要求的数

class Solution {
private:
    int count, maxCount = 0;
    TreeNode* pre = nullptr;
public:
    vector<int> findMode(TreeNode* root) {
        vector<int> ans;
        traversal(root, ans);
        return ans;
    }

    void traversal(TreeNode* cur, vector<int>& ans) {
        if(cur == nullptr) return ;
        // 中序遍历左子树
        traversal(cur->left, ans);

        // 处理逻辑
        // 当pre == nullptr时,此时遇到第一个节点,将count更新为1
        if(pre == nullptr) count = 1;
        // 如果前一个值和当前值不相等,则更新count记录新值的频率
        else if(pre->val != cur->val) {
            count = 1;
        } else {   // 如果当前值和前一个值相等,则count值加一
            count++;
        }
        // 如果count值和最高频率相等则将当前值保存到结果集中
        if(count == maxCount) ans.push_back(cur->val);
        // 如果count > maxCount 则将maxCount更新,并将结果集清空,将当前值假如结果集中
        else if(count > maxCount) {
            maxCount = count;
            ans.clear();
            ans.push_back(cur->val);
        }
        pre = cur;
        // 中序遍历右子树
        traversal(cur->right, ans);
    }
};

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

求公共祖先需要从下往上查找所以应该选择后续遍历
判断逻辑:如果递归遍历遇到q,就将q返回,遇到p 就将p返回,那么如果 左右子树的返回值都不为空,说明此时的中节点,一定是q 和p 的最近祖先。

如果q是p的祖先或者p是q的祖先,那么只要遇到其中一个就返回的逻辑已经满足了这种情况

题目链接 文章讲解 视频讲解

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if(root == nullptr) return nullptr;
        if(root == p || root == q) return root;
        // 后序遍历左子树
        TreeNode* left = lowestCommonAncestor(root->left, p, q);
        // 后序遍历右子树
        TreeNode* right = lowestCommonAncestor(root->right, p, q);
        // 处理逻辑
        if(left == nullptr && right != nullptr) return right;
        if(left != nullptr && right == nullptr) return left;
        if(left != nullptr && right != nullptr) return root;
        else return nullptr;
    }
};

标签:count,遍历,TreeNode,cur,随想录,nullptr,二叉,搜索,root
From: https://www.cnblogs.com/cscpp/p/18227772

相关文章

  • 城市之旅:使用 LLM 和 Elasticsearch 简化地理空间搜索(二)
    我们在之前的文章“城市之旅:使用LLM和Elasticsearch简化地理空间搜索(一)”,在今天的练习中,我将使用本地部署来做那里面的Jupyternotebook。安装Elasticsearch及Kibana如果你还没有安装好自己的Elasticsearch及Kibana,请参考如下的链接来进行安装:如何在Linux,Mac......
  • 代码随想录算法训练营第二十天 | 654.最大二叉树 617.合并二叉树 二叉搜索树
    654.最大二叉树题目链接文章讲解视频讲解classSolution{public:TreeNode*constructMaximumBinaryTree(vector<int>&nums){returninorderTraversal(nums,0,nums.size()-1);}TreeNode*inorderTraversal(vector<int>&nums,intbegi......
  • Part 3.1 深度优先搜索
    深度优先搜索(DFS),即按照深度优先的顺序搜索的算法。深度优先搜索一般使用栈来实现。[USACO1.5]八皇后CheckerChallenge题目描述一个如下的6×6......
  • [AIGC] 广度优先搜索(Breadth-First Search,BFS)详解
    广度优先搜索(Breadth-FirstSearch,简称BFS)是一种用于图或者树的搜索算法,它的特点是按照“广度”进行搜索,即在扩展搜索路线的时候,BFS会先考虑当前节点的所有邻近节点,也就是说,它逐层地进行搜索。文章目录基本原理实现方法应用场景总结基本原理广度优先搜索的基本......
  • 华为od机考_精准核酸检测_Java(深度优先搜索)
    华为od机考_精准核酸检测_Java题目为了达到新冠疫情精准防控的需要,为了避免全员核酸检测带来的浪费,需要精准還定可能被感染的人群。现在根据传染病流调以及大数据分析,得到了每个人之间在时间、空间上是否存在轨迹的交叉。现在给定一组确诊人员编号(X1,X2,X3,…Xn),在所有人当中......
  • 算法学习笔记——二分搜索
    二分搜索在有序数组中确定num存在还是不存在:当arr[m]==num,则num存在当arr[m]>num,则r=m-1,缩小r的范围,继续往左二分当arr[m]<num,则l=m+1,缩小l的范围,继续往右二分//保证arr有序,才能用这个方法publicstaticboolenexist(int[]arr,intnum){if(ar......
  • 代码随想录算法训练营第第25天 | 216.组合总和III 、17.电话号码的字母组合
    今天的题比较简单,重点是在于剪枝216.组合总和III如果把组合问题理解了,本题就容易一些了。题目链接/文章讲解:https://programmercarl.com/0216.组合总和III.html视频讲解:https://www.bilibili.com/video/BV1wg411873x/***@param{number}k*@param{number}n*@retu......
  • 二叉树链式结构的前序、中序、后序、层序遍历
    文章目录一、二叉树创建二、前序遍历概念以及解释代码三、中序遍历概念及解释代码四、后序遍历概念及解释代码五、层序遍历概念及解释代码一、二叉树创建&mesp; 实现二叉树的遍历,我们要先手搓出一个二叉树,在次基础上实现二叉树的前序、中序、后序、层序遍历。......
  • Q2 LeetCode35 搜索插入位置
    //有序查找,无重复元素,要求时间复杂度O(logn)//如果有目标元素则返回位置//如果没有目标元素,最后一次right位置后面就是该插入的位置第一次提交错误认为最后一次mid位置是插入的位置,其实最后一次right位置才是正确的插入位置(升序数组)1classSol......
  • 【数据结构】二叉树-堆(下)-链式二叉树
    个人主页~二叉树-堆(上)栈和队列二叉树四、堆的代码实现Heap.hHeap.ctest.c五、堆的应用堆排序思想进行排序六、二叉树链式结构的实现BTree.hBTree.ctest.c四、堆的代码实现Heap.h#pragmaonce#include<stdio.h>#include<stdlib.h>#include<assert.h>......