文章目录
前置知识
参考前文
参考文章:
LeetCode刷题笔记【9】:二叉树专题-1(分别用递归遍历、迭代遍历、标记遍历实现前、中、后序遍历)
LeetCode刷题笔记【10】:二叉树专题-2(二叉树的层序遍历、翻转二叉树、对称二叉树)
LeetCode刷题笔记【10.5】:二叉树专题-2.5(二叉树的层序遍历 - 10道题)
LeetCode刷题笔记【11】:二叉树专题-3(二叉树的最大深度、二叉树的最小深度、完全二叉树的节点个数)
LeetCode刷题笔记【12】:二叉树专题-4(平衡二叉树、二叉树的所有路径、左叶子之和)
LeetCode刷题笔记【13】:二叉树专题-5(找树左下角的值 、路径总和、从前序与中序遍历序列构造二叉树、从中序与后序遍历序列构造二叉树)
LeetCode刷题笔记【14】:二叉树专题-6(最大二叉树 、合并二叉树 、二叉搜索树中的搜索 、验证二叉搜索树)4
LeetCode刷题笔记【15】:二叉树专题-7( 二叉搜索树的最小绝对差、二叉搜索树中的众数、二叉树的最近公共祖先)
LeetCode刷题笔记【16】:二叉树专题-8(二叉搜索树的最近公共祖先、二叉搜索树中的插入操作、删除二叉搜索树中的节点)
669. 修剪二叉搜索树
题目描述
LeetCode链接:https://leetcode.cn/problems/trim-a-binary-search-tree/
挨个处理节点, 将问题转化为"删除非法节点"
思路: 遍历二叉树, 在过程中进行删除操作
关于遍历: 在过程中使用递归, 具体使用方法是让root->left = funx(root->left) & root->right = funx(root->right)
关于删除:
① 如果root->left
和root->right
都为nullptr
, 直接delete root, return nullptr
② 如果左右子树其中一个为nullptr
, 一个不是, 则delete root
, 返回非nullptr
的那个
③ 如果左右子树都非nullptr
, 则将root->left
拼贴到root->right
的最深最左节点下的左节点
class Solution {
public:
TreeNode* trimBST(TreeNode* root, int low, int high) {
cout << "!!!" << endl;
if(!root){
cout << "本节点为空" << endl;
return nullptr;
}
cout << root->val << endl;
if(root->val<low || root->val>high){
cout << "要删" << endl;
if(root->left==nullptr && root->right==nullptr){
cout << "左右都为空" << endl;
// delete root;
return nullptr;
}else if(root->left==nullptr && root->right!=nullptr){
cout << "左空右不空" << endl;
TreeNode* tmp = root->right;
// delete root;
return trimBST(tmp, low, high);
}else if(root->left!=nullptr && root->right==nullptr){
cout << "右空左不空" << endl;
TreeNode* tmp = root->left;
// delete root;
return trimBST(tmp, low, high);
}else{
cout << "左右都不空" << endl;
TreeNode* cur = root->right;
while(cur->left != nullptr){
cur = cur->left;
}
cur->left = root->left;
TreeNode* tmp = root->right;
// delete root;
return trimBST(tmp, low, high);
}
}
cout << root->val << endl;
cout << "不删" << endl;
root->left = trimBST(root->left, low, high);
root->right = trimBST(root->right, low, high);
cout << root->val << " final check" << endl;
return root;
}
};
参考这一期笔记中的最后一题, 方法思路是一样的.
LeetCode刷题笔记【16】:二叉树专题-8(二叉搜索树的最近公共祖先、二叉搜索树中的插入操作、删除二叉搜索树中的节点)
这里特别说一下, LeetCode的线上编译器其实有一定问题, 比如上面代码中的delete用法是对的, 并不会造成野指针和悬挂指针之类的问题, 但是LeetCode就是会报错, 但是本地编译器却不会.
原因可能是LeetCode可能将我要删除的节点指到什么乱七八糟的地方去了.
利用二叉搜索树性质, 直接大量剪枝
刚才的方法也是可以的, 但是它并没有完全利用到二叉搜索树的性质和特点
但其实如果cur->val<low
, 那么curNode
以及其left
, 都需要被删掉, 所以只要返回funx(cur->right)
即可
同理, if(cur->val>high), return funx(cur->left)
// class Solution {
// public:
// TreeNode* trimBST(TreeNode* root, int low, int high) {
// if(!root){
// return nullptr;
// }
// if(root->val<low){
// return trimBST(root->right, low, high);
// }else if(root->val>high){
// return trimBST(root->left, low, high);
// }
// root->left = trimBST(root->left, low, high);
// root->right = trimBST(root->right, low, high);
// return root;
// }
// };
108.将有序数组转换为二叉搜索树
题目描述
LeetCode链接:https://leetcode.cn/problems/convert-sorted-array-to-binary-search-tree/description/
解题思路
思路: 用限位指针left
和right
, 每次选取下标为(left+right)/2
的数, 建立node
node->left = funx(left, position-1)
, node->right = funx(position+1, right)
当left>right
的时候return
代码
class Solution {
public:
TreeNode* build(vector<int>& nums, int left, int right){
if(left>right)
return nullptr;
int position = (left+right)/2;
TreeNode* node = new TreeNode(nums[position]);
node->left = build(nums, left, position-1);
node->right = build(nums, position+1, right);
return node;
}
TreeNode* sortedArrayToBST(vector<int>& nums) {
return build(nums, 0, nums.size()-1);
}
};
538.把二叉搜索树转换为累加树
题目描述
LeetCode链接:https://leetcode.cn/problems/convert-bst-to-greater-tree/description/
解题思路
我们知道: 二叉搜索树如果进行中序遍历, 就可以得到递增序列;
那么同理, 如果进行反中序遍历, 就可以得到递减序列;
这样一来, 在过程中用一个sum
记录之前遍历过的节点的val
和;
然后每遍历一个节点, 将这个节点的val
加入sum
, 并将此节点的val
设为加后的sum
.
代码
class Solution {
private:
int sum=0;
public:
TreeNode* convertBST(TreeNode* root) {
if(root!=nullptr){
convertBST(root->right);
sum += root->val;
root->val = sum;
convertBST(root->left);
}
return root;
}
};
总结
首先是血泪教训: 很多时候LeetCode的报错并不是我们写的有问题, 就是他自己(的编译器)有问题.
(摸到自己编译环境的上限并琢磨明白或许是水平提高的特点呢(小小骄傲一下))
其次是今天第三题这种, 利用二叉搜索树中序遍历结果递增, 并且用pre和cur抽取其中的前后关系, 的操作, 还是不够熟练.
530. 二叉搜索树的最小绝对差
501. 二叉搜索树中的众数
之后可以多刷刷这几题
本文参考:
修剪二叉搜索树
将有序数组转换为二叉搜索树
把二叉搜索树转换为累加树