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

给你一个二叉搜索树的根节点 root ,返回 树中任意两不同节点值之间的最小差值。差值是一个正数,其数值等于两值之差的绝对值。

我的思路:先中序遍历得到二叉树的单调序列,然后检查每查询相邻两个之间的最小值。也可以不记录序列,只记录上一个差值就行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution {
public:
void traverse(TreeNode* root, vector<int> &midseq){
if(root == nullptr)return;
traverse(root->left, midseq);
midseq.emplace_back(root->val);
traverse(root->right, midseq);
}
int getMinimumDifference(TreeNode* root) {
vector<int> midseq;
traverse(root,midseq);
int mindiff = std::abs(midseq[1]-midseq[0]);
for(int i = 2;i<midseq.size();i++){
int dif = std::abs(midseq[i]-midseq[i-1]);
if(dif < mindiff){
mindiff = dif;
}
}
return mindiff;
}
};

2、501二叉搜索树中的众数

给你一个含重复值的二叉搜索树(BST)的根节点 root ,找出并返回 BST 中的所有 众数(即,出现频率最高的元素)。

我的思路:先用中序遍历得到一个递增序列,然后用双指针去序列里寻找频率最高的元素。其实我认为也可以直接当普通二叉树来处理,递归遍历存储节点出现频率再HashMap中,最后在map里寻找最大值。

代码随想录:也是两种思路,首先通用二叉树遍历用HashMap存储,然后转为vector排序(map不能排序)。第二种他是直接在递归的过程中就计算频率。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
// 我写的
class Solution {
public:
void traverse(TreeNode* root, vector<int> &midseq){
if(root == nullptr)return;
traverse(root->left, midseq);
midseq.emplace_back(root->val);
traverse(root->right, midseq);
}
vector<int> findMode(TreeNode* root) {
vector<int> midseq;
map<int,int> pq;
traverse(root,midseq);
int left = 0, right = 0;
vector<int> res;
int maxnum = 0;
while(right < midseq.size()){
while(right < midseq.size() && midseq[left]==midseq[right]){
right++;
}
if((right-left) == maxnum){
res.emplace_back(midseq[left]);
}
if((right-left) > maxnum){
res.clear();
res.emplace_back(midseq[left]);
maxnum = right-left;
}
left = right;
}
return res;
}
};
// 代码随想录
class Solution {
private:
int maxCount = 0; // 最大频率
int count = 0; // 统计频率
TreeNode* pre = NULL;
vector<int> result;
void searchBST(TreeNode* cur) {
if (cur == NULL) return ;

searchBST(cur->left); // 左
// 中
if (pre == NULL) { // 第一个节点
count = 1;
} else if (pre->val == cur->val) { // 与前一个节点数值相同
count++;
} else { // 与前一个节点数值不同
count = 1;
}
pre = cur; // 更新上一个节点

if (count == maxCount) { // 如果和最大值相同,放进result中
result.push_back(cur->val);
}

if (count > maxCount) { // 如果计数大于最大值频率
maxCount = count; // 更新最大频率
result.clear(); // 很关键的一步,不要忘记清空result,之前result里的元素都失效了
result.push_back(cur->val);
}

searchBST(cur->right); // 右
return ;
}

public:
vector<int> findMode(TreeNode* root) {
count = 0;
maxCount = 0;
pre = NULL; // 记录前一个节点
result.clear();

searchBST(root);
return result;
}
};

3、236二叉树的最近公共祖先

给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

百度百科最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

我的思路:没做出来。之前我一直想如果p或q是子树根节点,那我返回之后岂不是无法遍历到另一个节点了。后面看了代码随想录后懂了,返回之后就不要遍历另一个节点了,因为这个返回节点就是root,已经找到了。
代码随想录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// 看了代码随想录后写的
class Solution {
public:
TreeNode* traverse(TreeNode* root, TreeNode* p, TreeNode* q) {
if(root == nullptr || root == p || root == q)return root;

TreeNode* leftre = traverse(root->left,p,q);
TreeNode* righre = traverse(root->right,p,q);

if(leftre != nullptr && righre != nullptr)return root;
if(leftre != nullptr)return leftre;
if(righre != nullptr)return righre;
return nullptr;
}
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if(root == nullptr)return nullptr;
return traverse(root,p,q);
}
};
// 代码随想录
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if (root == q || root == p || root == NULL) return root;
TreeNode* left = lowestCommonAncestor(root->left, p, q);
TreeNode* right = lowestCommonAncestor(root->right, p, q);
if (left != NULL && right != NULL) return root;

if (left == NULL && right != NULL) return right;
else if (left != NULL && right == NULL) return left;
else { // (left == NULL && right == NULL)
return NULL;
}
}
};