代码随想录算法训练营第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

代码随想录算法训练营是一个优质的学习和讨论平台,提供了丰富的算法训练内容和讨论交流机会。在训练营中,学员们可以通过观看视频讲解来学习算法知识,并根据讲解内容进行刷题练习。此外,训练营还提供了刷题建议,例如先看视频、了解自己所使用的编程语言、使用日志等方法来提高刷题效果和语言掌握程度。 训练营中的讨论内容非常丰富,涵盖了各种算法知识点和解题方法。例如,在第14训练营中,讲解了二叉树的理论基础、递归遍历、迭代遍历和统一遍历的内容。此外,在讨论中还分享了相关的博客文章和配图,帮助学员更好地理解和掌握二叉树的遍历方法。 训练营还提供了每日的讨论知识点,例如在第15的讨论中,介绍了层序遍历的方法和使用队列来模拟一层一层遍历的效果。在第16的讨论中,重点讨论了如何进行调试(debug)的方法,认为掌握调试技巧可以帮助学员更好地解决问题和写出正确的算法代码。 总之,代码随想录算法训练营是一个提供优质学习和讨论环境的平台,可以帮助学员系统地学习算法知识,并提供了丰富的讨论内容和刷题建议来提高算法编程能力。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [代码随想录算法训练营每日精华](https://blog.youkuaiyun.com/weixin_38556197/article/details/128462133)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

tt555555555555

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值