654. 最大二叉树


本题已经给出了构造的要求,首先找到最大值,接着根据最大值分割数组,再递归构建左右子树。
和之前的根据后序和中序数组构造二叉树相似,下面给出代码:

class Solution {public:int getindedx(vector<int> vec){int val = INT_MIN;int ans;for(int i = 0; i < vec.size(); i++){if(vec[i] > val){ans = i;val = vec[i];}}return ans;}TreeNode* constructMaximumBinaryTree(vector<int>& nums) {if(nums.size() == 0) return NULL;int rootindex = getindedx(nums);TreeNode* root = new TreeNode(nums[rootindex]);if(nums.size() == 1) return root;vector<int> leftvec(nums.begin() , nums.begin() + rootindex);vector<int> rightvec(nums.begin() + rootindex + 1, nums.end());root->left = constructMaximumBinaryTree(leftvec);root->right = constructMaximumBinaryTree(rightvec);return root;}
};

这里我自己定义了一个寻找最大值的函数,其实没有必要,并且在性能和代码上还有很大的优化空间。下面是使用数组下标进行递归的优化代码:

class Solution {public:TreeNode* traversal(vector<int>& nums, int left, int right){if(left >= right) return NULL;int maxindex = left;for(int i = left + 1; i < right; i++){if(nums[maxindex] < nums[i]) maxindex = i;}TreeNode* root = new TreeNode(nums[maxindex]);root->left = traversal(nums, left, maxindex);root->right = traversal(nums, maxindex + 1, right);return root;}TreeNode* constructMaximumBinaryTree(vector<int>& nums) {return traversal(nums, 0, nums.size());}
};

这样节省了额外数组的内存开销,但是需要注意寻找最大值下标的时候的循环范围是left + 1right

617. 合并二叉树

本题主要是同时对两棵二叉树进行处理,实际上与处理一颗二叉树差不多,因为遍历两棵树的时候节点处理的顺序是相同的。
使用递归来写,本题使用前中后序遍历都可以,下面是递归三部曲:

  1. 输入输出:不需要额外再写一个递归函数,直接使用题目给的即可:TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2)
  2. 终止条件:这里的终止条件不能写两者都为空,这样在本题中没有意义,而是当两者其中一个为空时的处理
  3. 单层递归逻辑:这里使用前序,构造好节点后再递归构造左右子树

我自己写的是创建一个新的树来输出结果:

TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {if(root1 == NULL || root2 == NULL){if(root1 == NULL) return root2;else if(root2 == NULL) return root1;else return NULL;}int val1 = 0;int val2 = 0;if(root1) val1 = root1->val;if(root2) val2 = root2->val;TreeNode* root = new TreeNode(val1 + val2);root->left = mergeTrees(root1->left , root2->left);root->right = mergeTrees(root1->right , root2->right);//if(root1->left || root2->left) root->left = mergeTrees(root1->left , root2->left);//if(root1->right || root2->right) root->right = mergeTrees(root1->right , root2->right);return root;}

这里说一下我对终止条件的判断,以及对空节点的处理的理解:

  • 如果在终止条件里已经对空节点处理了,那么在递归左右孩子的时候可以不用加上if(root->left)这种代码;
  • 如果终止条件中需要对符合条件的节点进行处理的话,一般情况下这个节点不会为空节点,所以后面对左右孩子的递归不需要加上if(root->left)这种代码;
  • 当需要使用节点内的value时,需要注意空节点的问题,如果有以上两种情况的话实际上可以忽略,因为已经提前确保当前遍历节点不是空节点了。
  • 有时候也需要根据递归函数的返回值类型来决定

只是一些自己刷题的感想,也不一定对。

上述代码也可以进一步简化,比如终止条件那里,不需要对左右节点都为NULL的情况返回false,因为如果root1为NULL返回root2,root2为NULL返回root1已经包含了两者都为空的情况。另外可以直接对其中一个树直接操作,不用去额外构造一棵树。
代码如下:

TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {if(root1 == NULL) return root2;if(root2 == NULL) return root1;root1->val += root2->val;root1->left = mergeTrees(root1->left, root2->left);root1->right = mergeTrees(root1->right, root2->right);return root1;}

这样就看起来很简洁了。

700. 二叉搜索树中的搜索

本题使用迭代法来做甚至不需要使用队列或者栈来储存节点,因为二叉搜索树的特性,代码也非常简洁,也就不详细说了,代码如下:

TreeNode* searchBST(TreeNode* root, int val) {while(root){if(val < root->val) root = root->left;else if(val > root->val) root = root->right;else return root;;}return NULL;}

下面详细说一下递归法。
本题递归部分顺序,因为BST本身就是有序的,所以不需要确定前中后序。这里顺便说一下一个特性,在下一题中非常重要:BST的中序遍历是一个递增的数组
递归三部曲:

  1. 输入输出:使用函数本身来递归,TreeNode* searchBST(TreeNode* root, int val)
  2. 终止条件:先补充一个概念:空节点是一颗BST也是一颗完全二叉树、满二叉树;所以当节点为空时返回,当节点的值等于target时返回;
  3. 单层递归逻辑:由于BST的特性,当root->val大于target时,说明需要找的节点一定在root节点的左边,反之则在右边,这样就确定了左右递归的逻辑

递归代码如下:

TreeNode* searchBST(TreeNode* root, int val) {if(root == NULL || root->val == val) return root;TreeNode* ans = NULL;if(val < root->val) ans = searchBST(root->left, val);if(val > root->val) ans = searchBST(root->right, val);return ans;}

这里需要新定义一个TreeNode* ans来接收左右孩子遍历的结果,否则在遍历完左或者右孩子之后没有返回值。

98. 验证二叉搜索树

本题解题的核心思想就是上面提到的BST的中序遍历是递增的,所以思路是在遍历的时候将当前节点的值与前一个结点进行对比,如果大于则符合BST,如果小于则直接返回false。
最简单的写法就是遍历整颗二叉树,然后将结果输出到数组中,最后判断是否是BST,代码如下:

class Solution {private:vector<int> vec;void traversal(TreeNode* root) {if (root == NULL) return;traversal(root->left);vec.push_back(root->val); // 将二叉搜索树转换为有序数组traversal(root->right);}
public:bool isValidBST(TreeNode* root) {vec.clear(); // 不加这句在leetcode上也可以过,但最好加上traversal(root);for (int i = 1; i < vec.size(); i++) {// 注意要小于等于,搜索树里不能有相同元素if (vec[i] <= vec[i - 1]) return false;}return true;}
};

本题也可以使用双指针,在一个函数里直接完成解题步骤。因为BST的特性,所以按照中序遍历的递归来写递归函数。
递归三部曲:

  1. 输入输出:bool isValidBST(TreeNode* root),直接使用主函数,输入自然是结点,输出是bool
  2. 终止条件:前面也说了,空结点也是BST,所以终止条件为if(root == NULL)
  3. 单层递归逻辑:使用一个pre指针保存前一个结点,然后进行比较,按照中序的顺序写递归函数体

下面是具体代码:

 TreeNode* pre = NULL;bool isValidBST(TreeNode* root) {if(root == NULL) return true;bool left = isValidBST(root->left);if(pre && pre->val >= root->val) return false;pre = root;bool right = isValidBST(root->right);return left && right;}

总结

一个是返回值和返回类型的问题:最后一题是需要处理递归的结果的,所以需要返回值,并且同时需要两个遍历来接收左右孩子遍历的结果返回上一层;700. 二叉搜索树中的搜索中需要定义一个结点来存放返回值,如果在if语句中直接返回是不符合语法的。
一个是终止条件和空结点的问题:一般情况来说:如果让空节点(空指针)进入递归,就不加if,如果不让空节点进入递归,就加if限制一下, 终止条件也会相应的调整。
有点累,但还是要咬牙坚持,调整一下状态继续干二叉树!

代码随想录第二十天 LeetCode513、112、113、106、105相关推荐

  1. 代码随想录第17天|513,112,113,106,105

    文章目录 513.找树左下角的值 112. 路径总和 113.路径总和ii 106.从中序与后序遍历序列构造二叉树 105.从前序与中序遍历序列构造二叉树 513.找树左下角的值 本题要找出树的最后一 ...

  2. 代码随想录十八天|513,112,113,106,105

    513. 找树左下角的值 即找最后一行的最左侧 //递归法,前序 class Solution { public:int maxDepth = INT_MIN;int result;void trav ...

  3. 代码随想录一刷个人记录

    代码随想录一刷个人记录 2022/7/14(leetcode) 2022/7/15(leetcode) 2022/7/17[字符串] 2022/7/18[字符串] 2022/7/20[双指针] 202 ...

  4. 代码随想录之路经总和

    路径总和力扣112 路径总和|| 力扣113 本题的思路学习于代码随想录 JAVA版本 一.路径总和: 本题的思路较为简单,只需要用target来减去值即可. 解法一:使用递归的方法 class So ...

  5. 墙裂推荐!卡神力作《代码随想录》,上架首日卖爆!

    刚开始学习数据结构与算法,或者在力扣(LeetCode)上刷题的读者都有这种困惑--从何学起,先学什么,再学什么.很多人刷题的效率低,主要体现在以下三点: 难以寻找适合自己的题目. 找到了不合适现阶段 ...

  6. 送卡神算法力作《代码随想录》!

    刚开始学习数据结构与算法,或者在力扣(LeetCode)上刷题的读者都有这种困惑--从何学起,先学什么,再学什么.很多人刷题的效率低,主要体现在以下三点: 难以寻找适合自己的题目. 找到了不合适现阶段 ...

  7. 代码随想录Day48|198.打家劫舍、213.打家劫舍II、337.打家劫舍III

    文章目录 198.打0家劫舍 213.打家劫舍II 337.打家劫舍III 198.打0家劫舍 文章讲解:代码随想录 (programmercarl.com) 题目链接:198. 打家劫舍 - 力扣( ...

  8. 代码随想录算法训练营第二十二天

    235. 二叉搜索树的最近公共祖先 利用二叉搜索树的性质,同时学习了代码随想录,我们可以学到第一个遍历到的值在目标区间内的数为最近公共祖先,若值大于目标区间,就探索左子树:若值小于目标区间,就探索右子 ...

  9. 代码随想录算法训练营第一天 704 二分查找、27 移除元素

    代码随想录算法Day1 | 704. 二分查找.27. 移除元素 Last edited time: April 5, 2023 11:27 AM 数据理论基础 数组是存放在连续内存空间上的相同类型数 ...

  10. Leetcode 704.二分查找 27.移除元素 代码随想录day1

    本系列目的在于跟练代码随想录,以及记录自己在数据结构与算法方面的一些学习 704.二分查找 其实之前自己在随便刷题的时候看过这道题目,就是一个纯新手的大状态,第一次听到二分查找这样的东西,然后跟着题解 ...

最新文章

  1. metasploit-smb扫描获取系统信息
  2. vue 表格左右拖拽调整列宽_解决 | iview低版本实现表格拖拽,滚动条列宽计算问题...
  3. AIoT重磅报告:四大关键助力,AI+IoT重新定义未来的可能性
  4. 面向对象程序设计第二次作业
  5. easyui 初体验
  6. 2013-10-31 《三天里什么都没干……总之把目前为止的代码发了吧……》
  7. Python中安装模块的方法
  8. Java内存模型(Java Memory Model,简称JMM)
  9. css3文档手册chm_你还在使用CHM帮助文档吗?赶快试试Baklib吧
  10. echo print printf() sprintf()区别
  11. swift4 label显示html,Swift:在标签或textView中显示HTML数据
  12. 支付宝PC(二维码扫码)支付(Java开发)完整版
  13. PRi——自行车码表
  14. nginx常用伪静态设置
  15. C++,Linux架构师成长之路
  16. STM32定时器实现100毫秒保存一次数据到SD卡
  17. 51单片机(1)单片机概述
  18. 指定文件名无效或太长,请指定另一文件名
  19. 【Python】01基础语法
  20. 关于win10打开文件安全警告怎么关闭

热门文章

  1. 【前端学习-函数】js基础学习笔记
  2. 【jpa】简介和项目生成、API-初级入门
  3. https双向认证java
  4. stm32:时钟系统
  5. 爬取斗鱼主播名字和热度
  6. cents7 mysql数据库安装和配置
  7. 怎么把win10退回win7系统
  8. Volatility工具使用
  9. 上海提取公积金所需材料
  10. Oracle Data Guard官方说明