代码随想录算法训练营第二十三天| 669. 修剪二叉搜索树 108.将有序数组转换为二叉搜索树 538.把二叉搜索树转换为累加树 总结
669. 修剪二叉搜索树
卡哥建议:这道题目比较难,比 添加增加和删除节点难的多,建议先看视频理解。
题目链接/文章讲解:https://programmercarl.com/0669.%E4%BF%AE%E5%89%AA%E4%BA%8C%E5%8F%89%E6%90%9C%E7%B4%A2%E6%A0%91.html
做题思路:
递归处理,区间 [low, high],遇到 root->val < low || root->val > high
的时候直接return NULL,
还有一种情况考虑不符合区间的节点,它的左子树或者右子树有符合区间的节点,比如,那么将节点0的右孩子 节点2 直接赋给 节点3的左孩子就可以了(就是把节点0从二叉树中移除),如图:
本题代码:
1 class Solution {
2 public:
3 TreeNode* trimBST(TreeNode* root, int low, int high) {
4 if (root == nullptr ) return nullptr;
5 if (root->val < low) { //从根节点开始遍历,如果根节点小于区间左边界值,说明根节点是要修剪的节点,根据搜索树的特点,从根节点的右子树开始寻找符合区间的
6 TreeNode* right = trimBST(root->right, low, high); // 寻找符合区间[low, high]的节点
7 return right;
8 }
9 if (root->val > high) {
10 TreeNode* left = trimBST(root->left, low, high); // 寻找符合区间[low, high]的节点
11 return left;
12 }
13 root->left = trimBST(root->left, low, high); // root->left接入符合条件的左孩子
14 root->right = trimBST(root->right, low, high); // root->right接入符合条件的右孩子
15 return root;
16 }
17 };
108.将有序数组转换为二叉搜索树
卡哥建议:本题就简单一些,可以尝试先自己做做。
https://programmercarl.com/0108.%E5%B0%86%E6%9C%89%E5%BA%8F%E6%95%B0%E7%BB%84%E8%BD%AC%E6%8D%A2%E4%B8%BA%E4%BA%8C%E5%8F%89%E6%90%9C%E7%B4%A2%E6%A0%91.html
做题思路:
根据有序数组构造一棵二叉树。本质就是寻找分割点,分割点作为当前节点,然后递归左区间和右区间。分割点就是数组中间位置的节点。
如果数组长度为偶数,中间节点有两个,取哪一个都可以,只不过构成了不同的平衡二叉搜索树。
比如,如果要分割的数组长度为偶数的时候,中间元素为两个,是取左边元素 就是树1,取右边元素就是树2。
本题代码:
1 class Solution {
2 private:
3 TreeNode* traversal(vector<int>& nums, int left, int right) {
4 if (left > right) return nullptr; //非法区间
5 int mid = left + ((right - left) / 2); //切割点
6 TreeNode* root = new TreeNode(nums[mid]);
7 root->left = traversal(nums, left, mid - 1); //区间为左闭右闭,所以 mid-1 为对应下标的值,这里看卡哥视频理解
8 root->right = traversal(nums, mid + 1, right);
9 return root;
10 }
11 public:
12 TreeNode* sortedArrayToBST(vector<int>& nums) {
13 TreeNode* root = traversal(nums, 0, nums.size() - 1);
14 return root;
15 }
16 };
538.把二叉搜索树转换为累加树
卡哥建议:本题也不难,在 求二叉搜索树的最小绝对差 和 众数 那两道题目 都讲过了 双指针法,思路是一样的。
https://programmercarl.com/0538.%E6%8A%8A%E4%BA%8C%E5%8F%89%E6%90%9C%E7%B4%A2%E6%A0%91%E8%BD%AC%E6%8D%A2%E4%B8%BA%E7%B4%AF%E5%8A%A0%E6%A0%91.html
视频讲解:https://www.bilibili.com/video/BV1d44y1f7wP
做题思路:
二叉搜索树的有序数组,是按中序遍历得到的,就是左中右,那累加的话,理解题意后,就是从后到前加起来,顺序是右中左。
所以我们需要反中序遍历这个二叉树,然后顺序累加就可以了。
本题依然需要一个pre指针记录当前遍历节点cur的前一个节点,这样才方便做累加。
本题代码:
1 class Solution {
2 private:
3 int pre = 0; // 记录前一个节点的数值
4 void traversal(TreeNode* cur) { // 右中左遍历
5 if (cur == NULL) return;
6 traversal(cur->right); //右
7 cur->val += pre;//中
8 pre = cur->val;
9 traversal(cur->left);//左
10 }
11 public:
12 TreeNode* convertBST(TreeNode* root) {
13 pre = 0;
14 traversal(root);
15 return root;
16 }
17 };
总结:
https://programmercarl.com/%E4%BA%8C%E5%8F%89%E6%A0%91%E6%80%BB%E7%BB%93%E7%AF%87.html
本文作者:银河小船儿
本文链接:https://www.cnblogs.com/romantichuaner/p/17646804.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步