669 修剪,做了好久,因为非想用自己的方法实现
一开始就觉得跟删除没什么差别,按删除写的,最开始的问题是删除都写的不对,传参数的时候忘记不能只传* node要传 *&node才对
删除的实现改对了之后,还是逻辑有根本问题,以下是错误代码:
问题在于,每次node被修改之后新的node的val是会变的,也是需要再查一次的,但是要传到traverse里的话,整个traverse就乱了,而且还会有重复,反正跑出来是runtime error
void traverse(TreeNode * &node, int low, int high){
if(node==nullptr) return;
traverse(node->left, low, high);
TreeNode* tmp=node;
if(node->val<low ||node->val>high){
if(node->right==nullptr && node->left==nullptr) node=nullptr;
else if(node->right) node=node->right;
else if(node->left) node=node->left;
else{
TreeNode *leftmost=node->right;
while(leftmost->left){
leftmost=leftmost->left;
}
leftmost->left=node->left;
node=node->right;
}
if(tmp) traverse(tmp,low,high);
}
if(node && node->right) traverse(node->right, low, high);
}
TreeNode* trimBST(TreeNode* root, int low, int high) {
traverse(root,low,high);
return root;
}
而且我这个还没利用二叉搜索树有顺序
正确做法如下:
TreeNode* trimBST(TreeNode* root, int low, int high) {
if (root == nullptr) return root;
if (root->val > high) return trimBST(root->left, low, high);
if (root->val < low) return trimBST(root->right, low, high);
root->left = trimBST(root->left, low, high);
root->right = trimBST(root->right, low, high);
return root;
}
- 如果 root 为 null,我们直接返回 null。
- 如果 root 的值大于 high,那么所有右子节点都会大于 high,只需返回处理后的左子树。
- 如果 root 的值小于 low,那么所有左子节点都会小于 low,只需返回处理后的右子树。
- 如果 root 的值在范围内,处理左右子树,并更新 root 的左右子节点的引用,然后返回 root。
108 将有序数组转换为二叉搜索树
还是和gpt讨论了才通过的。我的大体思路是对的,但是想的特别复杂:
我当时自己写的是创好left和right的空node然后传进去,没必要,直接自己那一轮管自己的,自己创自己的node就行
然后就是 第二行这个写法不容易错
然后这个start>end的base case也很重要,一开始没写对
//int mid = start + (end - start) / 2;
int mid=(start+end)/2;
TreeNode* helper(vector<int>& nums, int start, int end) {
if (start > end) { // Base case: start > end, return NULL
return NULL;
}
int mid = start + (end - start) / 2;
TreeNode* node = new TreeNode(nums[mid]);
node->left = helper(nums, start, mid - 1);
node->right = helper(nums, mid + 1, end);
return node;
}
TreeNode* sortedArrayToBST(vector<int>& nums) {
return helper(nums, 0, nums.size() - 1);
}
538 累加树
我自己的方法是先遍历一遍求全体的和,然后减去,挺好想也挺好实现的
有一个点,我以为helper函数node需要传递&,其实发现不用ref,是copy也行
这里让我联想到第21天的#530 二叉搜索树的最小绝对差,那道题传的是prev的ref,如果不是ref就会出错。当时我的理解是,要改变树本身的东西我就需要传node ref。从这道题看到,其实不是的,那道题因为是因为不断变更了prev(哎其实我也有点说不清,先放在这里放着)
void traverse(TreeNode* node, int &sum){
if(node==nullptr) return;
traverse(node->left,sum);
sum+=node->val;
traverse(node->right,sum);
}
void helper(TreeNode* node, int sum, int & newsum){
if(node==nullptr) return;
helper(node->left,sum,newsum);
newsum+=node->val;
node->val+=sum-newsum;
helper(node->right,sum,newsum);
}
TreeNode* convertBST(TreeNode* root) {
int sum=0;
traverse(root,sum);
int newsum=0;
helper(root,sum, newsum);
return root;
}
随想录的思路是:反中序求和,右中左,很聪明,需要记录一个pre方便累加
int pre = 0; // 记录前一个节点的数值
void traversal(TreeNode* cur) { // 右中左遍历
if (cur == NULL) return;
traversal(cur->right);
cur->val += pre;
pre = cur->val;
traversal(cur->left);
}
TreeNode* convertBST(TreeNode* root) {
pre = 0;
traversal(root);
return root;
}
迭代法的话就是用中序模板改,改成右中左