本文最后更新于 2024年8月18日 下午
今日内容
●
654.最大二叉树
●
617.合并二叉树
●
700.二叉搜索树中的搜索
●
98.验证二叉搜索树
最大二叉树
一般写法
题目实际上已经给出了递归逻辑,翻译成代码即可
给定一个不重复的整数数组nums
。最大二叉树
可以用下面的算法从nums
递归地构建:
- 创建一个根节点,其值为
nums
中的最大值。
- 递归地在最大值
左边
的子数组前缀上
构建左子树。
- 递归地在最大值
右边
的子数组后缀上
构建右子树。
返回nums
构建的最大二叉树
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| class Solution { public: TreeNode* constructMaximumBinaryTree(vector<int>& nums) { if(nums.size() == 0) return nullptr; int max = 0; for(int i = 0;i < nums.size();i++) if(nums[max] < nums[i]) max = i; TreeNode * root = new TreeNode(nums[max]); vector<int> left(nums.begin(), nums.begin() + max); vector<int> right(nums.begin() + max + 1, nums.end()); root->left = constructMaximumBinaryTree(left); root->right = constructMaximumBinaryTree(right); return root; } };
|
单调栈写法
笔者仅根据题目写出递归写法,未想到单调栈写法,此为力扣官方题解启发
因此,我们的任务变为:找出每一个元素左侧和右侧第一个比它大的元素所在的位置。这就是一个经典的单调栈问题了,可以参考
503.
下一个更大元素
II。如果左侧的元素较小,那么该元素就是左侧元素的右子节点;如果右侧的元素较小,那么该元素就是右侧元素的左子节点。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| class Solution { public: TreeNode* constructMaximumBinaryTree(vector<int>& nums) { int len = nums.size(); if(len == 0){ return nullptr; } vector<int> left(len, -1); vector<int> right(len, -1); stack<int> stk; vector<TreeNode*> tree(len); for(int i = 0; i < len; i++){ tree[i] = new TreeNode(nums[i]); while(!stk.empty() && nums[i] > nums[stk.top()]){ right[stk.top()] = i; stk.pop(); } if(!stk.empty()){ left[i] = stk.top(); } stk.push(i); } TreeNode* root = nullptr; for(int i = 0; i < len; i++){ if(left[i] == -1 && right[i] == -1){ root = tree[i]; }else if(left[i] == -1 || (right[i] != -1 && nums[left[i]] > nums[right[i]])){ tree[right[i]]->left = tree[i]; }else{ tree[left[i]]->right = tree[i]; } } return root; } };
|
该代码中的注释来源于题解评论区@健,本菜比瞪眼看了十分钟没看懂,抄了,挖坑后面来看
合并二叉树
简单递归即可
- 确定返回值和参数:就按力扣给的核心函数递归就行,无需另写函数,返回值就是合并后的节点指针,参数就是要合并的两个节点
- 确定递归结束条件:如果一方为空则返回另一方,都不空则相加后返回和节点
- 确定递归中途操作:合并当前节点对应的左右孩子
1 2 3 4 5 6 7 8 9 10 11
| class Solution { public: TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) { if(!root1) return root2; if(!root2) return root1; root1->val += root2->val; root1->left = mergeTrees(root1->left, root2->left); root1->right = mergeTrees(root1->right, root2->right); return root1; } };
|
二叉搜索树中的搜索
过于简单,知道什么是二叉搜索树就能做,略
验证二叉搜索树
示例2就已经给出一个容易犯的陷阱:错误地以为只需要左右节点各比根节点小和大就可以了,实际上二叉搜索树需要整个左右子树都比根节点小和大,所以需要注意在想当然递归的时候不要只比较左右节点,还需注意更上层的节点。
由于是二叉搜索树,条件比较硬,所以可以充分利用二叉搜索树的特性————利用中序遍历获取序列,然后判断该序列是否单调递增就好,若不单调递增,证明不是二叉搜索树
二叉排序树左子树-根-右子树严格单调递增,标准地画出一棵二叉排序树,并从上到下作其投影可得到严格序列,该序列即是中序遍历序列,并且该序列单调递增
附图直观一览
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| class Solution { public: vector<long long> ans; void traversal(TreeNode * root) { if(root) { traversal(root->left); ans.push_back(root->val); traversal(root->right); } } bool isValidBST(TreeNode* root) { traversal(root); vector<long long> ans2 = ans; sort(ans2.begin(), ans2.end()); for(int i = 0;i < ans.size();i++) { if(ans[i] != ans2[i]) return false; if(i > 0 && ans2[i] <= ans2[i - 1]) return false; } return true; } };
|