代码随想录算法训练营第15天 | 第六章 二叉树 part05

654.最大二叉树

我写的代码算是比较直接的。一层层的递归,找到中间的最大值,创建结点,再找到左边最大,右边最大,指针指过去,但是一定要注意范围。我是直接创造左右子数组,最开始创建左子数组时,std::vector left(nums.begin(), nums.begin() + index - 1)会导致范围错误,因为当index == 1时,它会试图创建一个从nums.begin()到nums.begin()的空范围。因此,应该是nums.begin() + index而不是nums.begin() + index - 1。我还以为创建子数组时,函数里面是索引,结果发现,它更像一个左闭右开的区间范围。学到了。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    TreeNode* traversal(vector<int>& nums)
    {
        if(nums.empty())
        return nullptr;
        int index=0;
        
        for (int i = 0 ; i < nums.size(); ++i) {
            if (nums[i] > nums[index]) index = i;
        }
        TreeNode* root = new TreeNode(nums[index]);
        
        if(index>0)
        {
            std::vector<int> left(nums.begin(), nums.begin() +index);
            root->left=traversal(left);
            }
        else
        root->left=nullptr;
        
        if(index+1<nums.size())
        {
            std::vector<int> right(nums.begin() + index+1,nums.end());
            root->right=traversal(right);
            }
        else
        root->right=nullptr;
        return root;
    }
    TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
        return traversal(nums);
    }
};

题目链接/文章讲解:[link](https://programmercarl.com/0654.%E6%9C%80%E5%A4%A7%E4%BA%8C%E5%8F%89%E6%A0%91.html
视频讲解:link
连接中给的代码是传递左右区间索引值,方法更巧妙,因为不需要创建新数组,节省空间。

617.合并二叉树

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

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    TreeNode*  traversal(TreeNode* node1, TreeNode* node2)
    {
        if (node1 == NULL) return node2; // 如果t1为空,合并之后就应该是t2
        if (node2 == NULL) return node1; // 如果t2为空,合并之后就应该是t1
        node1->val += node2->val;
        node1->left=traversal(node1->left, node2->left);
        node1->right=traversal(node1->right, node2->right);
        return node1;
    }
    TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
        return traversal(root1, root2);
    }
};

还是挺简单的,递归法。没想到看完教学视频,居然一遍就写出来了。其实在不知不觉中,自己的代码能力也是有一点点的进步,还是要为自己加油点赞,也要为屏幕前的朋友点赞,日积月累,总会有进步的。
递归法,只要知道中止条件就是if (node1 == NULL) return node2;其实应该是左右都为空,但当左右都为空时候,这段直接返回空,所以不用担心。把第二颗树的值加到第一颗树上,然后处理左子节点和右子节点。思路还是比较简单的。
题目链接/文章讲解:[link] (https://programmercarl.com/0617.%E5%90%88%E5%B9%B6%E4%BA%8C%E5%8F%89%E6%A0%91.html)
视频讲解:link

700.二叉搜索树中的搜索

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

题目链接/文章讲解: link
视频讲解:link

递归法

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    TreeNode* traversal(TreeNode* node, int val){
        if (!node)
        return nullptr;
        if(node->val==val)
        return node;
        else if(node->val>val)
        return traversal( node->left, val);
        else//if(node->val>val)
        return traversal(node->right, val);

    }
    TreeNode* searchBST(TreeNode* root, int val) {
        return traversal(root,  val);
    }
};

越写越觉得递归法很简单。递归法,只要知道,输入什么,传出什么,怎么处理即可。二叉搜索树,传入结点和对比值,输出目标结点或者空指针。这时候,只要因为二叉搜索树的节点是有序的,所以可以有方向的去搜索。如果root->val > val,搜索左子树,如果root->val < val,就搜索右子树,最后如果都没有搜索到,就返回NULL。返回什么就返回什么类型,层层外包,但也要层层负责,一旦发现了,就从村->乡->县->市->省->中央一层层押送找到的犯人。
tips: else//if(node->val>val)
return traversal(node->right, val);发现,函数中必须要返回,不能只用if else if。计算机很傻,保证一定返回,一定要加上else。确保一定有返回值保证结束。

迭代法

对于二叉搜索树,不需要回溯的过程,因为节点的有序性就帮我们确定了搜索的方向。回溯是要把整个遍历完,不断试错。但是如果不需要把整个遍历完,就不需要回去重新探索。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    TreeNode* searchBST(TreeNode* root, int val) {
       while (root != NULL) {
            if (root->val > val) root = root->left;
            else if (root->val < val) root = root->right;
            else return root;
        }
        return NULL;
    }
};

二叉搜索树确实简单,思路很清晰确实挺简单,感动哭了。玛德总算来了道简单题。

98.验证二叉搜索树

遇到 搜索树,一定想着中序遍历,这样才能利用上特性。

但本题是有陷阱的,可以自己先做一做,然后在看题解,看看自己是不是掉陷阱里了。这样理解的更深刻。
可以递归中序遍历将二叉搜索树转变成一个数组,然后只要比较一下,这个数组是否是有序的,注意二叉搜索树中不能有重复元素。
确实有陷阱,我最开始也以为只要判断左右子树即可。后来发现最关键的,左子树的右子树可能会比自己要大,或者右子树的左子树比自己小。不符合条件,被误判
在这里插入图片描述
注意要小于等于,搜索树里不能有相同元素

if(!root)
        {return ;}
        if(root->left)
        {
            traversal(root->left)
        }
        vec.push_back(root->val);
        if(root->right)
        {
            traversal(root->left)
        }
        return ;

最开始写的代码如上,但是看了下代码随想录的,怎么这么巧妙,没必要判断左右是否为空,为空就返回.

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<int> vec;
    
    void traversal(TreeNode* root)
    {
         if (root == NULL) return;
        traversal(root->left);
        vec.push_back(root->val); // 将二叉搜索树转换为有序数组
        traversal(root->right);
    }    
    bool isValidBST(TreeNode* root) {
        traversal(root);
    for (int i = 1; i < vec.size(); i++) { 
        if (vec[i] <= vec[i - 1]) return false;
    }
        return true;
    }
};

这题本质上就成为了一个中序遍历题,还是比较简单的。
题目链接/文章讲解:link
视频讲解:link

  • 21
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值