Day20
654.最大二叉树
跟中序后序构造数组思路差不多,都是先建立根节点(寻找符合条件的数值),然后确定左右子树的范围。
一般情况来说:如果让空节点(空指针)进入递归,就不加if,如果不让空节点进入递归,就加if限制一下, 终止条件也会相应的调整。
class Solution {
public:
TreeNode* travelsal(vector<int>& nums,int left,int right){
if(left==right) return NULL;
int delimiter=left;
for(int i=left;i<right;i++){
if(nums[i]>nums[delimiter]) delimiter=i;
}
TreeNode* root=new TreeNode(nums[delimiter]);
int leftleft=left;
int leftright=delimiter;
int rightleft=delimiter+1;
int rightright=right;
root->left=travelsal(nums,leftleft,leftright);
root->right=travelsal(nums,rightleft,rightright);
return root;
}
TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
if(nums.size()==0) return NULL;
return travelsal(nums,0,nums.size());
}
};
617.合并二叉树
合并二叉树本质上其实也是遍历,只不过是每次左右同时进行,还需要注意的一点是当其中一个二叉树(比如t1)的孩子为空的时候,最后合并完的部分一定是另一个子树的所有值,所以只需要将t2的孩子节点返回就行了,后面的那些就不用处理了(这也是为什么可以用层序遍历)
递归:
class Solution {
public:
TreeNode* travelsal(TreeNode* t1,TreeNode* t2){
if(t1==NULL) return t2;
if(t2==NULL) return t1;
if(t1!=NULL &&t2!=NULL){
t1->val+=t2->val;
}
t1->left=travelsal(t1->left,t2->left);
t1->right=travelsal(t1->right,t2->right);
return t1;
}
TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
return travelsal(root1,root2);
}
};
迭代法:层序遍历的思路
class Solution {
public:
TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
if(root1==NULL) return root2;
if(root2==NULL) return root1;
queue<TreeNode*> que;
que.push(root1);
que.push(root2);
while(!que.empty()){
TreeNode* node1=que.front();
que.pop();
TreeNode* node2=que.front();
que.pop();
node1->val+=node2->val;
if(node1->left!=NULL &&node2->left!=NULL){
que.push(node1->left);
que.push(node2->left);
}
if(node1->left==NULL){
node1->left=node2->left;
}
if(node1->right!=NULL &&node2->right!= NULL){
que.push(node1->right);
que.push(node2->right);
}
if(node1->right==NULL){
node1->right=node2->right;
}
}
return root1;
}
};
700.二叉搜索树中的搜索
对于递归法,重点还是返回值怎么处理的问题,一个函数的返回值只是代表这个函数运行完之后的返回值(像本题,search的返回值需要确实是一个节点,但是需要用一个变量来表示,比如下面的result)。
class Solution {
public:
TreeNode* search(TreeNode* root,int val){
if(root==NULL) return NULL;
TreeNode* result;
if(root->val==val){
return root;
}
else if(root->val>val){
result=search(root->left,val);
}
else{
result=search(root->right,val);
}
return result;
}
TreeNode* searchBST(TreeNode* root, int val) {
return search(root,val);
}
};
迭代法:
本题迭代法确实不需要队列和栈,(因为已经树有序了,所以只需要按照路径走就可以了),不需要搜索其他节点,也不需要做回溯,查找的路径已经规划好了。
class Solution {
public:
TreeNode* searchBST(TreeNode* root, int val) {
if(root==NULL) return NULL;
TreeNode* node=root;
while(node!=NULL){
if(node->val>val){
node=node->left;
}
else if(node->val==val){
return node;
}
else{
node=node->right;
}
}
return NULL;
}
};
98.验证二叉搜索树
之前没做过,只判断了左右元素跟根节点的大小比较。但是除了这个比较之外,他其实还要跟根节点的父节点比较。
看了题解之后发现二叉排序树其实就是按照中序遍历有序,所以只需要按照中序遍历,然后比较前后元素大小就好了。
递归法:
class Solution {
public:
TreeNode* pre=NULL;
bool isValid(TreeNode* node){
if(node==NULL) return true;
bool left=isValid(node->left);
if(pre!=NULL&&pre->val>=node->val) return false;
pre=node;
bool right=isValid(node->right);
return left&&right;
}
bool isValidBST(TreeNode* root) {
return isValid(root);
}
};
迭代法:
我使用统一迭代法写的,卡在pre怎么写好长时间,最后发现应该写在一开始的if语句中,提出NULL的时候才证明这个节点被拿出来了。
class Solution {
public:
bool isValidBST(TreeNode* root) {
stack<TreeNode*> st;
if(root==NULL) return true;
st.push(root);
TreeNode* pre=NULL;
while(!st.empty()){
TreeNode* node=st.top();
st.pop();
if(node==NULL){
node=st.top();
st.pop();
if(pre!=NULL&&pre->val>=node->val){
return false;
}
pre=node;
cout<<node->val<<endl;
}
else{
if(node->right)st.push(node->right);
st.push(node);
st.push(NULL);
if(node->left) st.push(node->left);
}
}
return true;
}
};