今天是二叉树学习的第六天。主要的学习内容有:二叉搜索树相关题目,以及找出二叉树中任意两点的公共祖先问题。
530.二叉搜索树的最小绝对差
题目链接:530. 二叉搜索树的最小绝对差 - 力扣(LeetCode)
这个题的背景是二叉搜索树,所以一定是使用中序遍历完成。题目求解的是任意两个节点的最小绝对差,由于中序遍历的二叉搜索树是单调递增的,我们可以沿用双指针的方法,并且对最小绝对差进行一个动态的更新。具体代码实现如下:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
TreeNode* pre=NULL;
int min=100010;
void order(TreeNode* root)
{
if(root==NULL) return;
order(root->left);
if(pre!=NULL&&root->val-pre->val<min) min=root->val-pre->val;
pre=root;
order(root->right);
}
int getMinimumDifference(TreeNode* root) {
order(root);
return min;
}
};
使用迭代法也是类似的思想,具体代码实现如下:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
int getMinimumDifference(TreeNode* root) {
stack<TreeNode*> st;
TreeNode* pre=NULL;
TreeNode* cur=root;
int min=100010;
while(cur!=NULL||!st.empty())
{
if(cur!=NULL)
{
st.push(cur);
cur=cur->left;
}
else
{
cur=st.top();
st.pop();
if(pre!=NULL&&cur->val-pre->val<min) min=cur->val-pre->val;
pre=cur;
cur=cur->right;
}
}
return min;
}
};
501.二叉搜索树中的众数
题目链接:501. 二叉搜索树中的众数 - 力扣(LeetCode)
我拿到这个题目的思路是用map去记录二叉搜索树的所有数值以及出现次数,将这个map设置成一个vector,然后手写一个快速排序,根据每个数值出现的次数从大到小排序并输出。具体代码如下:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
void order(TreeNode* root,unordered_map<int,int> &map)
{
if(root==NULL) return;
order(root->left,map);
map[root->val]++;
order(root->right,map);
}
void quick_sort(vector<pair<int,int>> &result,int l,int r)
{
if(l>=r) return;
int i=l-1;
int j=r+1;
int k=l+r>>1;
int mid=result[k].second;
while(j>i)
{
do i++;while(result[i].second>mid);
do j--;while(result[j].second<mid);
if(j>i) swap(result[i],result[j]);
}
quick_sort(result,l,k);
quick_sort(result,k+1,r);
}
vector<int> findMode(TreeNode* root) {
unordered_map<int,int> map;
order(root,map);
vector<pair<int,int>> result(map.begin(),map.end());
quick_sort(result,0,result.size()-1);
vector<int> s;
s.push_back(result[0].first);
for(int i=1;i<result.size();i++)
{
if(result[i].second==result[0].second) s.push_back(result[i].first);
}
return s;
}
};
后来参考了随想录的题解,通过递归维护一个count和max_count,并根据根节点进行更新。挺巧妙的。具体代码实现如下:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> result;
int max_count=1;
int count=0;
TreeNode* pre=NULL;
void order(TreeNode* root)
{
if(root==NULL) return;
order(root->left);
if(pre!=NULL&&pre->val==root->val) count++;
else if(pre==NULL)
{
count++;
}
else{
count=1;
}
pre=root;
if(count==max_count) result.push_back(root->val);
if(count>max_count)
{
max_count=count;
result.clear();
result.push_back(root->val);
}
order(root->right);
}
vector<int> findMode(TreeNode* root) {
order(root);
return result;
}
};
使用迭代法也是一样的思路。具体代码实现如下:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> findMode(TreeNode* root) {
vector<int> result;
stack<TreeNode*> st;
TreeNode* cur=root;
TreeNode* pre=NULL;
int count=0;
int max_count=1;
while(cur!=NULL||!st.empty())
{
if(cur!=NULL)
{
st.push(cur);
cur=cur->left;
}
else
{
cur=st.top();
st.pop();
if(pre!=NULL&&pre->val==cur->val) count++;
else if(pre==NULL) count++;
else count=1;
pre=cur;
if(count==max_count) result.push_back(cur->val);
if(count>max_count)
{
result.clear();
max_count=count;
result.push_back(cur->val);
}
cur=cur->right;
}
}
return result;
}
};
236. 二叉树的最近公共祖先
题目链接:236. 二叉树的最近公共祖先 - 力扣(LeetCode)
我自己的实现方法是,通过递归和回溯得到根节点到目标节点的路径,然后将两条路径从后往前遍历,找到第一个相同的节点就是他们的公共祖先。具体代码实现如下:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
void order(TreeNode* root,vector<TreeNode*> &vec,TreeNode* p,vector<TreeNode*>& result)
{
vec.push_back(root);
if(root==NULL) return;
if(root==p)
{
result=vec;
}
if(root->left!=NULL)
{
order(root->left,vec,p,result);
vec.pop_back();
}
if(root->right!=NULL)
{
order(root->right,vec,p,result);
vec.pop_back();
}
}
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
vector<TreeNode*> result1;
vector<TreeNode*> result2;
vector<TreeNode*> vec;
order(root,vec,p,result1);
vec.clear();
order(root,vec,q,result2);
for(int i=result1.size()-1;i>=0;i--)
{
for(int j=result2.size()-1;j>=0;j--)
{
if(result1[i]==result2[j])
{
return result1[i];
}
}
}
return root;
}
};
然后参考了一下随想录的题解。随想录的做法是通过后续遍历,如果存在p或q就直接返回该节点,如果某节点的左子树和右子树都不为空,说明该节点为目标节点的公共祖先。将该节点层层返回即可得到答案。确实感觉自己想的话想不到这样的做法。具体代码实现如下:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if(root==NULL) return NULL;
if(root==p||root==q) return root;
TreeNode* left=lowestCommonAncestor(root->left,p,q);
TreeNode* right=lowestCommonAncestor(root->right,p,q);
if(left!=NULL&&right!=NULL) return root;
else if(left==NULL&&right!=NULL) return right;
else if(left!=NULL&&right==NULL) return left;
else return NULL;
}
};