530.二叉搜索树的最小绝对差
视频讲解:需要掌握如何遍历双指针!
这是一棵二叉搜索树,中序遍历就是有序地,最直观的想法就是把该树转换成有序数组,然后再找数组中的最小差值。但是这样增加了空间复杂度,其实我们可以在遍历过程中就能找到最小绝对差。
我们需要用一个pre节点记录当前遍历到的节点cur的前一个节点,中序遍历,每个节点的值是递增的,在此过程中我们就可以边遍历边比较cur与pre的差值。
/**
* 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 {
private:
int result = INT_MAX;
TreeNode* pre = NULL;
void traversal(TreeNode* cur)
{
if (!cur) return;
traversal(cur->left); // 左
if (pre != NULL) // 中
{
result = result < (cur->val - pre->val) ? result : (cur->val - pre->val);
}
pre = cur; // 记录前一个节点
traversal(cur->right); // 右
}
public:
int getMinimumDifference(TreeNode* root) {
traversal(root);
return result;
}
};
501.二叉搜索树中的众数
题目链接:二叉搜索树中的众数
视频讲解:不仅双指针,还有代码技巧可以惊艳到你!
主要思路还是遍历二叉树时用一前一后两个指针比较它们值的大小,相等时让计数器加1,不相等让计数器置1。在此过程中要记录出现次数最多的值,有可能不同的值出现最多次数一样。
/**
* 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 {
private:
TreeNode* pre = NULL;
vector<int> res;
int cnt = 0;
int cntMax = 0;
void travesal(TreeNode* cur)
{
if (!cur) return;
travesal(cur->left);
if (pre == NULL)
cnt = 1;
else if (pre->val == cur->val)
cnt++;
else
cnt = 1;
pre = cur;
if (cnt == cntMax) res.push_back(cur->val);
if (cnt > cntMax)
{
cntMax = cnt;
res.clear();
res.push_back(cur->val);
}
travesal(cur->right);
}
public:
vector<int> findMode(TreeNode* root) {
travesal(root);
return res;
}
};
236. 二叉树的最近公共祖先
题目链接:二叉树的最近公共祖先
视频讲解:自底向上查找,有点难度!
递归
1、确定递归函数返回值和参数
要的得到最近公共节点,返回值是TreeNode*,那么如果遇到p或q,就把p或q返回,如果返回值不为空,就说明找到了p或q;
2、确定终止条件
节点为空时,返回空。如果节点是p或q,将其返回,用于判断最近公共祖先;
3、确定单层递归逻辑
需要从下往上遍历,采取后序遍历的方法。遍历时,如果找到p或q就往上一层提供一个返回值,上一层不为空表示找到它们,把该层节点回溯返回到根节点。
回溯的过程
-
求最小公共祖先,需要从底向上遍历,那么二叉树,只能通过后序遍历(即:回溯)实现从底向上的遍历方式。
-
在回溯的过程中,必然要遍历整棵二叉树,即使已经找到结果了,依然要把其他节点遍历完,因为要使用递归函数的返回值(也就是代码中的left和right)做逻辑判断。
-
要理解如果返回值left为空,right不为空为什么要返回right,为什么可以用返回right传给上一层结果。
可以说这里每一步,都是有难度的,都需要对二叉树,递归和回溯有一定的理解。
本题没有给出迭代法,因为迭代法不适合模拟回溯的过程。理解递归的解法就够了。
/**
* 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; // root就是最近公共节点
if (left != NULL && right == NULL) return left; // 说明目标节点是通过left返回的
else if (left == NULL && right != NULL) return right; // 说明目标节点是通过right返回的
else return NULL;
}
};