530.二叉搜索树的最小绝对差
需要领悟一下二叉树遍历上双指针操作,优先掌握递归
题目链接/文章讲解:代码随想录
视频讲解:二叉搜索树中,需要掌握如何双指针遍历!| LeetCode:530.二叉搜索树的最小绝对差_哔哩哔哩_bilibili
这道题在二叉搜索树上求最小值,应注意二叉搜索树中序遍历为递增序列,最小绝对值差一定存在于连续两节点大减小,递增序列可以由中序遍历得到。
这道题好在练习了二叉树双指针递归,一个后指针由函数穿参,一个前指针为全局变量,在递归函数推出前赋值实现了在cur的前位。
class Solution {
public:
int min_diff = INT_MAX;
TreeNode* pre;
void traverse(TreeNode* cur){
if(cur == nullptr) return;
traverse(cur->left);
if(pre!=nullptr){
min_diff = min(cur->val-pre->val,min_diff);
}
pre = cur;
traverse(cur->right);
}
int getMinimumDifference(TreeNode* root) {
traverse(root);
return min_diff;
}
};
501.二叉搜索树中的众数
初步想法是遍历后用map统计,但是发现c++ map没有按照val排序的
和 530差不多双指针思路,不过 这里涉及到一个很巧妙的代码技巧。
写代码的时候有点混乱,不知道count应该记录cur还是pre,应该是cur,
pre设置一个只有一次的初始化,即pre==nullptr,
代码技巧:
class Solution {
public:
vector<int> results;
TreeNode* pre;
int maxCount = INT_MIN;
int count = 0;
void traverse(TreeNode* cur){
if(cur == nullptr) return;
traverse(cur->left);
if(pre == nullptr) count =1;
else if(pre->val == cur->val){
count++;
}else{
count = 1;
}
pre = cur;
if(count == maxCount){
results.push_back(cur->val);
}
if(count > maxCount){
maxCount = count;
results.clear();
results.push_back(cur->val);
}
traverse(cur->right);
}
vector<int> findMode(TreeNode* root) {
if(root==nullptr) return {};
if(root->left == nullptr && root->right == nullptr) return {root->val};
traverse(root);
return results;
}
};
视频讲解:不仅双指针,还有代码技巧可以惊艳到你! | LeetCode:501.二叉搜索树中的众数_哔哩哔哩_bilibili
236. 二叉树的最近公共祖先
视频讲解:自底向上查找,有点难度! | LeetCode:236. 二叉树的最近公共祖先_哔哩哔哩_bilibili
if(root==nullptr) return nullptr;
if(root->val == p->val) return p;
if(root->val == q->val) return q;
TreeNode* left = lowestCommonAncestor(root->left,p,q);
TreeNode* right = lowestCommonAncestor(root->right,p,q);
if((left == p && right == q)||(left == q && right == p)) return root;
if(left != nullptr) return left;
if(right!= nullptr) return right;
return nullptr;
235. 二叉搜索树的最近公共祖先
利用二叉搜索树的特性:默念n遍!根节点大于所有左子树的节点值,小于所有右子树的节点值。
往下找到第一个在两个值中间的节点就是最近公共祖先。
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if(root==nullptr) return nullptr;
TreeNode* ptr = root;
while((ptr->val < p->val)&&(ptr->val < q->val)||(ptr->val > p->val)&&(ptr->val > q->val)){
if((ptr->val > p->val)&&(ptr->val > q->val)) ptr = ptr->left;
else{
ptr = ptr->right;
}
}
return ptr;
}
};
题目链接/文章讲解:代码随想录
视频讲解:二叉搜索树找祖先就有点不一样了!| 235. 二叉搜索树的最近公共祖先_哔哩哔哩_bilibili
701.二叉搜索树中的插入操作
二叉树插入永远在叶子节点
还是左小右大的特性,根节点只需要修改一边子树。
递归思路,判断根节点值,如果大于加入节点值,那么是左子树要修改,递归左子树,只需要更新root->left所值对象就行
右子树同理。
动态试图会是一条到叶子节点的路径走下去(zig-zag),然后返回到root。
题目链接/文章讲解:代码随想录
视频讲解:原来这么简单? | LeetCode:701.二叉搜索树中的插入操作_哔哩哔哩_bilibili
450.删除二叉搜索树中的节点
一共三种情况:
1)左右皆空
2)一边空
3)两边都有,需要取右子树最小的节点替代。其中涉及删除替代节点。
class Solution {
public:
TreeNode* deleteNode(TreeNode* root, int key) {
if(root==nullptr) return nullptr;
if(root->val == key){
if(root->left == nullptr && root->right == nullptr){
root = nullptr;
return root;
}
if(root->left==nullptr){
root = root->right;
return root;
}
if(root->right == nullptr){
root = root->left;
return root;
}
TreeNode* ptr = root->right;
while(ptr->left!=nullptr){
ptr = ptr->left;
}
root->right = deleteNode(root->right,ptr->val);
ptr->left = root->left;
ptr->right = root->right;
root = ptr;
return root;
}
if(root->val < key)root->right = deleteNode(root->right,key);
if(root->val > key) root->left = deleteNode(root->left,key);
return root;
}
};
题目链接/文章讲解:代码随想录