代码随想录算法训练营第二十三天| 669. 修剪二叉搜索树 108.将有序数组转换为二叉搜索树 538.把二叉搜索树转换为累加树 总结

发布时间 2023-08-26 13:27:30作者: 银河小船儿
 

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

     视频讲解:https://www.bilibili.com/video/BV17P41177ud

      做题思路:

       递归处理,区间 [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

    视频讲解:https://www.bilibili.com/video/BV1uR4y1X7qL

    做题思路:

     根据有序数组构造一棵二叉树。本质就是寻找分割点,分割点作为当前节点,然后递归左区间和右区间。分割点就是数组中间位置的节点。

    如果数组长度为偶数,中间节点有两个,取哪一个都可以,只不过构成了不同的平衡二叉搜索树。

    比如,如果要分割的数组长度为偶数的时候,中间元素为两个,是取左边元素 就是树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