本文主要是介绍【算法训练 day23 二叉搜索树的最小绝对差、二叉搜索树的众数、二叉树的最近公共祖先】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
目录
- 一、二叉搜索树的最小绝对差-LeetCode 530
- 思路
- 实现代码
- 递归处理
- 使用数组
- 个人问题
- 二、二叉搜索树的众数-LeetCode 501
- 思路
- 实现代码
- map统计计数
- 递归过程中计数
- 个人问题
- 三.二叉树的最近公共祖先-LeeCode 236
- 思路
- 实现代码
- 个人问题
- 总结
一、二叉搜索树的最小绝对差-LeetCode 530
Leecode链接: leetcode 977
文章链接: 代码随想录
视频链接: B站
给你一个二叉搜索树的根节点 root ,返回 树中任意两不同节点值之间的最小差值 。
示例:
输入:root = [4,2,6,1,3]
输出:1
思路
解法1:转化为数组,然后逐个计算差值,返回最小差值即可。解法2:由于题目是搜索树,所以差值最小必定出现在相邻节点,使用全局变量保存上一个节点,中间节点计算差值并保存可能的最小差值。
实现代码
递归处理
//cpp
class Solution {
public:TreeNode* pre = nullptr;int minnum = INT32_MAX;void test(TreeNode* root){if(root == nullptr) return;test(root->left);if(pre != nullptr){minnum = min(minnum,root->val - pre->val);}pre = root;test(root->right);}int getMinimumDifference(TreeNode* root) {test(root);return minnum;}
};
使用数组
//cpp
class Solution {
private:
vector<int> vec;
void traversal(TreeNode* root) {if (root == NULL) return;traversal(root->left);vec.push_back(root->val); // 将二叉搜索树转换为有序数组traversal(root->right);
}
public:int getMinimumDifference(TreeNode* root) {vec.clear();traversal(root);if (vec.size() < 2) return 0;int result = INT_MAX;for (int i = 1; i < vec.size(); i++) { // 统计有序数组的最小差值result = min(result, vec[i] - vec[i-1]);}return result;}
};
个人问题
对于使用双指针还不够熟练。
二、二叉搜索树的众数-LeetCode 501
Leecode链接: LeetCode 501
文章链接: 代码随想录
视频链接: B站
给你一个含重复值的二叉搜索树(BST)的根节点 root ,找出并返回 BST 中的所有 众数(即,出现频率最高的元素)。
如果树中有不止一个众数,可以按 任意顺序 返回。
示例:
输入:root = [1,null,2,2]
输出:[2]
思路
两种解法:1.中序遍历形成map数组,然后对数组进行排序,可得众数。2.递归过程中计算众数,使用一个计数器,每遇到相同的值count加1,遇到不同的值count恢复为1,然后使用maxcount记录可能成为众数出现的频率。遍历完整个树为止。
实现代码
map统计计数
//cpp
class Solution {
private:void searchBST(TreeNode* cur, unordered_map<int, int>& map) { // 前序遍历if (cur == NULL) return ;map[cur->val]++; // 统计元素频率searchBST(cur->left, map);searchBST(cur->right, map);return ;
}
bool static cmp (const pair<int, int>& a, const pair<int, int>& b) {return a.second > b.second;
}
public:vector<int> findMode(TreeNode* root) {unordered_map<int, int> map; // key:元素,value:出现频率vector<int> result;if (root == NULL) return result;searchBST(root, map);vector<pair<int, int>> vec(map.begin(), map.end());sort(vec.begin(), vec.end(), cmp); // 给频率排个序result.push_back(vec[0].first);for (int i = 1; i < vec.size(); i++) {// 取最高的放到result数组中if (vec[i].second == vec[0].second) result.push_back(vec[i].first);else break;}return result;}
};
递归过程中计数
//cpp
class Solution {
public:int count = 0;int maxcount = 0;vector<int> res;TreeNode* pre = nullptr;void test(TreeNode* root){if(root == nullptr){return;}test(root->left);if(pre == nullptr){count = 1;}else if(root->val == pre->val){count++;}else{count = 1;}if(count>maxcount){maxcount = count;res.clear();res.push_back(root->val);}else if(count == maxcount){res.push_back(root->val);}pre = root;test(root->right);return;}vector<int> findMode(TreeNode* root) {res.clear();test(root);return res;}
};
个人问题
在实现代码时,maxcount的更新位置写在了root->val != pre->val的条件分支中,导致没有存储真正的众数;count初始值最初个人设置为1,但在执行时出现访问未定义行为,原因在于count初始值手动设置为1,但pre初始值也为1,导致不能访问正确的第一个元素的值。
三.二叉树的最近公共祖先-LeeCode 236
Leecode链接: LeetCode 236
文章链接: 代码随想录
视频链接: B站
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
示例:
输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
输出:3
解释:节点 5 和节点 1 的最近公共祖先是节点 3 。
思路
使用后序遍历,考虑一个一般情况,两个节点为某个父节点的左右子树,如果找到了该节点左右子树的递归函数就返回该节点的指针给父节点的这一层函数,这一层根据返回结果返回对应指针,如果都存在,表明要找的节点就在该父节点的孩子节点中,返回父节点自身即可。考虑一个特殊情况,如果两个节点互为父子节点,这时直接返回最先遇到的节点指针即可,如果一侧为空返回另一侧不为空的节点指针。
实现代码
//cpp
class Solution {
public:TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {if(root == NULL) return NULL;if(root->val==p->val||root->val==q->val)return root;TreeNode* left_p = lowestCommonAncestor(root->left,p,q);TreeNode* right_p = lowestCommonAncestor(root->right,p,q);if(left_p&&right_p)return root;else if(!left_p&&right_p) return right_p;else if(left_p&&!right_p) return left_p;else return NULL;}
};
个人问题
代码没有自己写出来。
总结
本题比较巧妙,对各个情况处理比较特殊。
这篇关于【算法训练 day23 二叉搜索树的最小绝对差、二叉搜索树的众数、二叉树的最近公共祖先】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!