代码随想录算法训练营第二十天| 654.最大二叉树 617.合并二叉树 700.二叉搜索树中的搜索 98.验证二叉搜索树

发布时间 2023-08-21 14:24:33作者: 银河小船儿
 

 654.最大二叉树 

     卡哥建议:又是构造二叉树,昨天大家刚刚做完 中序后序确定二叉树,今天做这个 应该会容易一些, 先看视频,好好体会一下 为什么构造二叉树都是 前序遍历 

    题目链接/文章讲解:https://programmercarl.com/0654.%E6%9C%80%E5%A4%A7%E4%BA%8C%E5%8F%89%E6%A0%91.html

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

     做题思路:

     构造树一般采用的是前序遍历,因为先构造中间节点,然后递归构造左子树和右子树。当递归遍历的时候,如果传入的数组大小为1,说明遍历到了叶子节点了。

  1. 先要找到数组中最大的值和对应的下标, 最大的值构造根节点,下标用来下一步分割数组。
  2. 最大值所在的下标左区间 构造左子树
  3. 最大值所在的下标右区间 构造右子树

     每次分隔不用定义新的数组,而是通过下标索引直接在原数组上操作。

    本题代码:

 1 class Solution {
 2 private:
 3     // 在左闭右开区间[left, right),构造二叉树
 4     TreeNode* traversal(vector<int>& nums, int left, int right) {
 5         if (left >= right) return nullptr; //区间要合法
 6 
 7         // 分割点下标:maxValueIndex
 8         int maxValueIndex = left;
 9         for (int i = left + 1; i < right; ++i) {
10             if (nums[i] > nums[maxValueIndex]) maxValueIndex = i;
11         }
12 
13         TreeNode* root = new TreeNode(nums[maxValueIndex]); //中
14 
15         // 左闭右开:[left, maxValueIndex)
16         root->left = traversal(nums, left, maxValueIndex); //左
17 
18         // 左闭右开:[maxValueIndex + 1, right)
19         root->right = traversal(nums, maxValueIndex + 1, right); //右
20 
21         return root;
22     }
23 public:
24     TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
25         return traversal(nums, 0, nums.size()); //传入数组和数组区间
26     }
27 };

 

617.合并二叉树 

    卡哥建议:这次是一起操作两个二叉树了, 估计大家也没一起操作过两个二叉树,也不知道该如何一起操作,可以看视频先理解一下。 优先掌握递归。

    题目链接/文章讲解:https://programmercarl.com/0617.%E5%90%88%E5%B9%B6%E4%BA%8C%E5%8F%89%E6%A0%91.html

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

    做题思路:

     两个树的根,左子树,右子树相加,

    因为是传入了两个树,那么就有两个树遍历的节点 t1 和 t2,如果t1 == NULL 了,两个树合并就应该是 t2 了(如果t2也为NULL也无所谓,合并之后就是NULL)。反过来如果 t2 == NULL,那么两个数合并就是 t1(如果t1也为NULL也无所谓,合并之后就是NULL)。

    这里我们重复利用一下t1这个树,t1就是合并之后树的根节点(就是修改了原来树的结构)。

    接下来t1 的左子树是:合并 t1左子树 t2左子树之后的左子树。

    t1 的右子树:是 合并 t1右子树 t2右子树之后的右子树。最终t1就是合并之后的根节点。

    本题代码:

1 TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) {
2         if (t1 == NULL) return t2; // 如果t1为空,合并之后就应该是t2
3         if (t2 == NULL) return t1; // 如果t2为空,合并之后就应该是t1
4         // 修改了t1的数值和结构
5         t1->val += t2->val;                             //
6         t1->left = mergeTrees(t1->left, t2->left);      //
7         t1->right = mergeTrees(t1->right, t2->right);   //
8         return t1;
9     }

 

 700.二叉搜索树中的搜索 

      卡哥建议:递归和迭代 都可以掌握以下,因为本题比较简单, 了解一下 二叉搜索树的特性

     题目链接/文章讲解: https://programmercarl.com/0700.%E4%BA%8C%E5%8F%89%E6%90%9C%E7%B4%A2%E6%A0%91%E4%B8%AD%E7%9A%84%E6%90%9C%E7%B4%A2.html

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

      做题思路:

     二叉搜索树是一个有序树:

  • 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
  • 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
  • 它的左、右子树也分别为二叉搜索树

     因为二叉搜索树的节点是有序的,所以可以有方向的去搜索。

     如果root->val > val,搜索左子树,如果root->val < val,就搜索右子树,最后如果都没有搜索到,就返回NULL。

     本题代码:

1 TreeNode* searchBST(TreeNode* root, int val) {
2         if (root == NULL || root->val == val) return root;
3         TreeNode* result = NULL;
4         if (root->val > val) result = searchBST(root->left, val);
5         if (root->val < val) result = searchBST(root->right, val);
6         return result;
7     }

 

98.验证二叉搜索树 

       卡哥建议:遇到搜索树,一定想着中序遍历,这样才能利用上特性。 但本题是有陷阱的,可以自己先做一做,然后在看题解,看看自己是不是掉陷阱里了。这样理解的更深刻。

     题目链接/文章讲解:https://programmercarl.com/0098.%E9%AA%8C%E8%AF%81%E4%BA%8C%E5%8F%89%E6%90%9C%E7%B4%A2%E6%A0%91.html

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

     做题思路:

      要知道中序遍历下,输出的二叉搜索树节点的数值是有序序列。有了这个特性,验证二叉搜索树,就相当于变成了判断一个序列是不是递增的了。

    可以递归中序遍历将二叉搜索树转变成一个数组,然后只要比较一下,这个数组是否是有序的,注意二叉搜索树中不能有重复元素。

    关于注意事项看卡哥视频和文章。

     本题代码:

 1 class Solution {
 2 private:
 3     vector<int> vec;
 4     void traversal(TreeNode* root) { //中序遍历
 5         if (root == NULL) return;
 6         traversal(root->left);
 7         vec.push_back(root->val); // 将二叉搜索树转换为有序数组
 8         traversal(root->right);
 9     }
10 public:
11     bool isValidBST(TreeNode* root) {
12         vec.clear(); // 不加这句在leetcode上也可以过,但最好加上
13         traversal(root);
14         for (int i = 1; i < vec.size(); i++) {
15             // 注意要小于等于,搜索树里不能有相同元素
16             if (vec[i] <= vec[i - 1]) return false;
17         }
18         return true;
19     }
20 };