代码随想录算法训练营第18天|669. 修剪二叉搜索树、108.将有序数组转换为二叉搜索树、538. 把二叉搜索树转换为累加树
LeetCode669
2025-02-17 21:08:10 星期一
题目描述:力扣669
文档讲解:代码随想录(programmercarl)669. 修剪二叉搜索树
视频讲解:《代码随想录》算法视频公开课:你修剪的方式不对,我来给你纠正一下!| LeetCode:669. 修剪二叉搜索树
代码随想录视频内容简记
本题的核心问题就是:究竟是返回当前结点递归的子树和还是当前结点的子树
另外就是感觉BST对递归的遍历顺序要求不那么高了,本题和前一天的235,701,450一样,在单层递归的逻辑上不再对中间结点进行单独处理,而是放到了一开始的递归的终止条件中。
梳理
-
确定函数的参数和返回值
-
确定递归的终止条件
-
确定单层递归的逻辑
大致代码内容
-
if (root == NULL) return NULL
-
确定递归的终止条件
1.首先是向左
if (root->val < low) left = traversal(root->right, low, high); return left
,这里有个小细节,就是对if的判断,root的值小于low下边界,那么其左子树就自然不用在进行遍历,因为更小,所以直接遍历其右子树即可。注意这里的写法,直接定义了left
,而没有直接返回root->left
,这里接上了之前的疑问。之前写701的时候,纠结于那个
root->left = traversal(root->left)
能不能换成TreeNode* left = insertIntoBST(root->left, val);return left;
就和669这里一模一样的写法。现在又看了一下,发现不同的步骤应该用不同的写法。梳理一下:
-
[确定递归的终止条件]
TreeNode* left = insertIntoBST(root->left, val);return left;
应该这么写 -
[确定单层递归的逻辑] 就不能按照上面那么写了,因为要root要接住他的子树,所以只能
root->left = traversal(root->left)
因为701的
之后回答上面的核心问题,放在这里就是能不能直接返回一个
return root->right
而不是traversal
后的子树呢?答案是不能2.向右同理
- 确定单层递归的逻辑
root->left = traversal(root->left, low, high)
,注意这里遍历的是root->left
。向右同理
LeetCode测试
代码比较简单😉,一遍就过了
点击查看代码
class Solution {
public:
TreeNode* trimBST(TreeNode* root, int low, int high) {
if (root == NULL) return NULL;
if (root->val < low) {
TreeNode* left = trimBST(root->right, low, high);
return left;
}
if (root->val > high) {
TreeNode* right = trimBST(root->left, low, high);
return right;
}
root->left = trimBST(root->left, low, high);
root->right = trimBST(root->right, low, high);
return root;
}
};
LeetCode108
题目描述:力扣108
文档讲解:代码随想录(programmercarl)108.将有序数组转换为二叉搜索树
视频讲解:《代码随想录》算法视频公开课:构造平衡二叉搜索树!| LeetCode:108.将有序数组转换为二叉搜索树
代码随想录视频内容简记
这个题目的核心就是不断寻找中间的结点来构造一棵平衡二叉搜索树,其实我也没想到平衡二叉树是这么构造的
-
确定函数的参数和返回值
-
确定递归的终止条件
-
确定单层递归的逻辑
大致代码内容
-
首先构建一个
TreeNode* traversal(vector<int>& nums, int left, int right)
这里有一个小细节,就是引用,k哥说到这么做是为了消除对地址的重复拷贝,导致程序性能下降,如果用引用的话,只需要在同样的地址中进行操作即可。 -
确定递归的终止条件,这里的终止条件就是一个非法的空间,来构建一个新的结点
if (left >= right) return NULL;
,之后TreeNode* root = new TreeNode(nums[mid]);
-
确定单层递归的逻辑,宝宝。这里首先要确定是左闭右闭还是左闭右开,因为又是在区间内进行操作。这里用左闭右开,
root->left = traversal(nums, left, mid)
,同理root->right = traversal(nums, mid + 1, right);
,最后直接return即可。
LeetCode测试
下午写到这里,力扣突然宕机了😅

这里注意一个小细节,半天一直是报stackoverflow

找了半天,是递归的终止条件写错了,因为我写的是左闭右开,所以left == right
也是一个非法区间,就得把等于号加上
完整代码如下
点击查看代码
class Solution {
private:
TreeNode* traversal(vector<int>& nums, int left, int right) {
int mid = (left + right) / 2;
if (left >= right) return NULL;
TreeNode* root = new TreeNode(nums[mid]);
root->left = traversal(nums, left, mid);
root->right = traversal(nums, mid + 1, right);
return root;
}
public:
TreeNode* sortedArrayToBST(vector<int>& nums) {
TreeNode* root = traversal(nums, 0, nums.size());
return root;
}
};
LeetCode538
题目描述:力扣538
文档讲解:代码随想录(programmercarl)538. 把二叉搜索树转换为累加树
视频讲解:《代码随想录》算法视频公开课:普大喜奔!二叉树章节已全部更完啦!| LeetCode:538.把二叉搜索树转换为累加树
代码随想录视频内容简记
这道题要求是BST转换成一棵累加树,思路是这样的,一个从小到大排列的数组按照从后向前累加,那么得到的就是一个累加数组,累加树就是这么来的
比如:[2, 5, 8]
的累加树,就是[15, 13, 8]
,从后向前加即可
梳理
-
确定函数的参数和返回值。这个函数比较特殊,用的是“右中左”遍历,也是中序,但是是从大到小的中序。另外,因为是直接在原树上进行修改,并不需要辅助空间,直接定义void函数即可
-
确定递归的终止条件。
-
确定单层递归的逻辑。
大致代码内容
-
这次直接定义了一个
int pre
来记录cur
结点的内容。然后需要单独定义一个void traversal(TreeNode* root)
函数 -
确定递归的终止条件,
if (cur == NULL) return;
-
单层递归的逻辑
-
向右,
traversal(cur->right);
-
中间,
cur->val += pre;
-
向左,
traversal(cur->left);
-
LeetCode测试
代码比较简洁,整体如下
点击查看代码
class Solution {
private:
int pre = 0;
void traversal(TreeNode* cur) {
if (cur == NULL) return;
traversal(cur->right);
cur->val += pre;
pre = cur->val;
traversal(cur->left);
}
public:
TreeNode* convertBST(TreeNode* root) {
traversal(root);
return root;
}
};
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端