文章目录
前置知识
参考前文
参考文章:
LeetCode刷题笔记【9】:二叉树专题-1(分别用递归遍历、迭代遍历、标记遍历实现前、中、后序遍历)
LeetCode刷题笔记【10】:二叉树专题-2(二叉树的层序遍历、翻转二叉树、对称二叉树)
LeetCode刷题笔记【10.5】:二叉树专题-2.5(二叉树的层序遍历 - 10道题)
LeetCode刷题笔记【11】:二叉树专题-3(二叉树的最大深度、二叉树的最小深度、完全二叉树的节点个数)
LeetCode刷题笔记【12】:二叉树专题-4(平衡二叉树、二叉树的所有路径、左叶子之和)
LeetCode刷题笔记【13】:二叉树专题-5(找树左下角的值 、路径总和、从前序与中序遍历序列构造二叉树、从中序与后序遍历序列构造二叉树)
654.最大二叉树
题目描述
LeetCode链接:https://leetcode.cn/problems/maximum-binary-tree/description/
递归法
思路: 创建辅助递归函数, 用left和right表示子串的左右坐标, 先选其中最大, 再递归调用传入左右子串儿
class Solution {
public:
TreeNode* build(vector<int>& nums, int left, int right){
if(nums.size()==0 || left>right){
return nullptr;
}
int position, maxNum=INT_MIN;
for(int i=left; i<=right; ++i){
if(nums[i]>maxNum){
maxNum = nums[i];
position = i;
}
}
TreeNode* node = new TreeNode(maxNum);
node->left = build(nums, left, position-1);
node->right = build(nums, position+1, right);
return node;
}
TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
return build(nums, 0, nums.size()-1);
}
};
遍历 + 单调栈
上一种方法中对于每个子串都需要遍历找最大值, 时间复杂度是O(n^2)
只遍历一次数组(时间复杂度O(n)
, 在过程中维护一个单调栈(栈顶为小, 栈底为大)
对于数组中当前遍历的数字k
① 新建val=k的节点node
② 如果k>top
, 就pop
, 并且在pop
的过程中不断让node->left = top
③ 如果②后栈不为空, 则top->right = node
④ st.push(node)
⑤ 遍历完nums
以后, 返回栈底元素
class Solution {
public:
TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
stack<TreeNode*> st;
for(int k : nums){
TreeNode* node = new TreeNode(k);
while(!st.empty() && k>st.top()->val){
node->left = st.top();
st.pop();
}
if(!st.empty()){
st.top()->right = node;
}
st.push(node);
}
TreeNode* ans;
while(!st.empty()){
ans = st.top();
st.pop();
}
return ans;
}
};
617.合并二叉树
题目描述
LeetCode链接:https://leetcode.cn/problems/merge-two-binary-trees/description/
解题思路
其实也是遍历, 但是对每个遍历节点的操作有所不同
代码
class Solution {
public:
TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
TreeNode* ans;
if(root1==nullptr) return root2;
if(root2==nullptr) return root1;
ans = root1;
ans->val += root2->val;
ans->left = mergeTrees(root1->left, root2->left);
ans->right = mergeTrees(root1->right, root2->right);
return ans;
}
};
700.二叉搜索树中的搜索
题目描述
LeetCode链接:https://leetcode.cn/problems/search-in-a-binary-search-tree/description/
解题思路
思路: 根据二叉搜索树的性质进行定向查找
cur->val < val
: 向右侧查找
cur->val > val
: 向左侧查找
代码
class Solution {
public:
TreeNode* searchBST(TreeNode* root, int val) {
if(root==nullptr || root->val == val)
return root;
if(root->val < val)
return searchBST(root->right, val);
if(root->val > val)
return searchBST(root->left, val);
return nullptr;
}
};
98.验证二叉搜索树
题目描述
LeetCode链接:https://leetcode.cn/problems/validate-binary-search-tree/description/
错误思路(坑)
思路: 进行遍历, 检测curNode->val
是否在curNode->left->val
和curNode->right->val
之间
// class Solution {
// public:
// bool isValidBST(TreeNode* root) {
// if(root==nullptr)
// return true;
// if(root->left && root->val <= root->left->val){
// return false;
// }
// if(root->right && root->val >= root->right->val){
// return false;
// }
// return isValidBST(root->left) && isValidBST(root->right);
// }
// };
递归传递合法范围, 检测当前节点是否合法
以上方法只检测一层的大小关系, 无法进行更远关系的检测, 比如**[5,4,6,null,null,3,7]
**
所以需要一路传过来更远的关系
class Solution {
public:
bool check(TreeNode* root, long long minNum, long long maxNum){
if(root==nullptr)
return true;
if(root->val <= minNum || root->val >= maxNum)
return false;
return check(root->left, minNum, root->val) && check(root->right, root->val, maxNum);
}
bool isValidBST(TreeNode* root) {
return check(root, LONG_MIN, LONG_MAX);
}
};
遍历得到中序遍历序列, 检测是否递增
可以在过程中比较, 也可以先一整个遍历结束再比较;
那就是遍历生成整个树的中序遍历, 然后再check
class Solution {
public:
void traversal(TreeNode* root, vector<long long>& marker){
if(root==nullptr)
return;
if(root->left)
traversal(root->left, marker);
marker.push_back(root->val);
if(root->right)
traversal(root->right, marker);
return;
}
bool isValidBST(TreeNode* root) {
vector<long long> marker;
traversal(root, marker);
// return is_sorted(marker.begin(), marker.end());
// 这里没法用is_sorted, 因为它检测的升序是不严格升序, 包括=的情况, 还得是要自己写
if(marker.size()==0 || marker.size()==1)
return true;
for(int i=0; i<marker.size()-1; ++i){
if(marker[i]>=marker[i+1])
return false;
}
return true;
}
};