LeetCode 654 最大二叉树
题目链接:https://leetcode.cn/problems/maximum-binary-tree/
思路:
我的思路是和昨天的前序与中序(中序与后序)构造二叉树的思路基本一样。
代码:
完整版-使用新数组
/**
* 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* constructMaximumBinaryTree(vector<int>& nums) {
if(nums.empty()) return nullptr;
return traversal(nums);
}
TreeNode* traversal(vector<int>&nums)
{
// 第一步
// 处理空节点
if(nums.size()==0) return nullptr;
// 第二步
// 寻找节点元素
int Max = 0;
int index = 0;
for(int i = 0;i<nums.size();i++)
{
if(nums[i]>Max)
{
Max = nums[i];
index = i;
}
}
// cout<<index<<endl;
TreeNode *root = new TreeNode(Max);
// 第三步
// 分割左右数组
vector<int>left(nums.begin(),nums.begin()+index);
vector<int>right(nums.begin()+index+1,nums.end());
// cout<<"------------------------"<<endl;;
// cout<<"left:"<<endl;
// for(int i:left)
// cout<<i<<" ";
// cout<<endl;
// cout<<"right:"<<endl;
// for(int i:right)
// cout<<i<<" ";
// cout<<endl;
// 第四步
// 递归左右子树
root->left = traversal(left);
root->right = traversal(right);
return root;
}
};
优化版-使用下标
/**
* 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* constructMaximumBinaryTree(vector<int>& nums) {
if(nums.empty()) return nullptr;
return traversal(nums,0,nums.size());
}
TreeNode* traversal(vector<int>&nums,int left,int right)
{
// 第一步
// 处理空节点
if(left>=right) return nullptr;
// 第二步
// 寻找节点元素
int index = left;
for(int i = left+1;i<right;i++)
{
if(nums[i]>nums[index])
index = i;
}
TreeNode *root = new TreeNode(nums[index]);
// 第三步
// 递归左右子树
root->left = traversal(nums,left,index);
root->right = traversal(nums,index+1,right);
return root;
}
};
总结
和昨天通过遍历方式构造二叉树类似,使用数组的方法自己可以完整写出来。使用下标的方法,在计算下标处还是有问题。
LeetCode 617 合并二叉树
题目链接:https://leetcode.cn/problems/merge-two-binary-trees/
思路:
采用前序遍历进行合并
代码:
/**
* 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* mergeTrees(TreeNode* root1, TreeNode* root2) {
// 终止条件
if(!root1) return root2;
if(!root2) return root1;
// 中
TreeNode *root = new TreeNode(0);
root->val = root1->val+root2->val;
// 左
root->left = mergeTrees(root1->left,root2->left);
// 右
root->right = mergeTrees(root1->right,root2->right);
return root;
}
};
总结
没有想象中那么复杂,算是第一道显性的操作两棵二叉树的题目。
LeetCode 700 二叉搜索树中的搜索
题目链接:https://leetcode.cn/problems/search-in-a-binary-search-tree/
思路:
二叉搜索树是一个有序树:
若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
它的左、右子树也分别为二叉搜索树
所以如果给的值小于根节点的值,那么我们往它的左子树去寻找;如果大于,那么往右子树方向去寻找。
代码:
递归法:
自写
/**
* 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) {
if(root==nullptr) return nullptr;
if(root->val == val)
return root;
TreeNode *result = new TreeNode();
if(root->val>val)
result = searchBST(root->left,val);
if(root->val<val)
result = searchBST(root->right,val);
return result;
}
};
简洁版
/**
* 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) {
if(!root||root->val==val) return root;
if(root->val>val) return searchBST(root->left,val);
if(root->val<val) return searchBST(root->right,val);
return nullptr;
}
};
迭代法
/**
* 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)
{
if(root->val>val) root = root->left;
else if(root->val<val) root = root->right;
else return root;
}
return nullptr;
}
};
总结
要利用二叉搜索树(BFS)的特性来进行遍历。
LeetCode 98 验证二叉搜索树
题目链接:https://leetcode.cn/problems/validate-binary-search-tree/
思路:
在中序遍历下二叉搜索树是一个有序数组。
注:空节点也是二叉搜索树。
陷阱
陷阱1:
不能单纯的仅仅比较左节点小于中间节点,右节点大于中间节点。
写出类似的代码:
if (root->val > root->left->val && root->val < root->right->val) {
return true;
} else {
return false;
}
这样是错误的。因为我们要求的是左右子树都满足二叉搜索树的特性,即左子树所有节点小于中间节点,右子树所有节点大于中间节点。
很容易出现这样的错误:
陷阱2:
在leetcode中最小节点可以取到int的最小值,所以使用最小的int来比较是不行的。
此时可以初始化比较元素为longlong的最小值。
然而,问题可以进一步延展:如果leetcode中根节点的val 可能是longlong的最小值,又要怎么办呢?
答:此时我们就可以定义一个TreeNode*记录前一个节点,用前一个节点与当前节点做比较,从而避免了使用最小值。
代码:
利用中序遍历递归法
/**
* 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>result;
bool isValidBST(TreeNode* root) {
result.clear();
inorder(root);
for(int i = 1;i<result.size();i++)
{
if(result[i]<=result[i-1])
return false;
}
return true;
}
void inorder(TreeNode *cur)
{
if(!cur) return;
inorder(cur->left);
result.push_back(cur->val);
inorder(cur->right);
}
};
直接递归法
/**
* 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 *pre = nullptr; // 用来记录前一个节点
bool isValidBST(TreeNode* root) {
// 终止条件
if(!root) return true;
// 左
bool left = isValidBST(root->left);
// 中
if(pre&&pre->val>=root->val) return false; // 二叉搜索树不能有相同元素
// 更新pre
pre = root;
// 右
bool right = isValidBST(root->right);
return left&&right; // 取交集,因为左右子树都要是二叉搜索树
}
};
迭代法
/**
* 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:
bool isValidBST(TreeNode* root) {
if(!root) return true;
stack<TreeNode*>st;
TreeNode *cur = root;
TreeNode *pre = nullptr;
while(cur||!st.empty())
{
if(cur)
{
st.push(cur);
cur = cur->left;
}
else
{
cur = st.top();
st.pop();
if(pre&&pre->val>=cur->val)
return false;
pre = cur;
cur = cur->right;
}
}
return true;
}
};
总结
要记住遇到二叉搜索树,要想着中序遍历,从而发挥出二叉搜索树的特性。因为中序遍历可以将二叉搜索树遍历成一个有序的数组。
今日总结:
学到了二叉搜索树,复习了中序遍历的迭代法。可以写出来最大二叉树的题目,将昨天学到的内容也复习了。、收获很多,继续加油!