DAY21|二叉树PART5

513. 找树左下角的值

找到最后一层的第一个数。
非递归的话,感觉一下子可以想到层序遍历?
层序遍历可以数层数,但是要如何知道这是最后一层啊。
感觉也不是不能做,可以存一下每层弹出的第一个元素(也就是最左边的元素),然后最后退出循环的时候这个空间里存的就是最底层最左边的元素,返回这个节点的值就可以了。
要不然就是先遍历求总的层数(深度),然后再次遍历到最后一层取最左边的元素。

按照第一个思路,写了一个AC的

/**
 * 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:
    int findBottomLeftValue(TreeNode* root) {
        queue<TreeNode*> myque;
        TreeNode* result;
        myque.push(root);
        
        while(myque.empty()==0){
            int size=myque.size();
            result=myque.front();
            while(size--){
                TreeNode* t=myque.front();
                myque.pop();
                if(t->left) myque.push(t->left);
                if(t->right) myque.push(t->right);
            }
        }
        return result->val;
    }

};

递归法的话:
如果按左中右顺序递归,需要返回当前节点的深度,最后取一个深度最大最左面的节点作为结果。
需要前序遍历,因为深度需要从上往下计数。保证取深度最大的节点,然后左边优先。

/**
 * 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:
    int result;
    int max_depth=INT_MIN;
    int findBottomLeftValue(TreeNode* root) {
        process(root,0);
        return result;
    }
    void process(TreeNode* root, int depth){
        if(root==nullptr) return;
        if(root->left==nullptr&&root->right==nullptr){
            if(depth>max_depth){
                result=root->val;
                max_depth=depth;
            }
        }
        process(root->left,depth+1);
        
        process(root->right,depth+1);
        
    }
};

递归,需要多练。

112.路经总和

因为(最差的情况的话)要遍历所有头节点到叶节点的路径找是否有相似的和,相当于每找到一条路径之和就比对一下。也是用到了回溯算法。
用回溯的话就要和递归放在一起用。

/**
 * 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 hasPathSum(TreeNode* root, int targetSum) {
        bool result=false;
        if(root==nullptr) return false;
        int sum=0;
        process(root,sum,result,targetSum);
        return result;
    }
    void process(TreeNode* root, int& sum, bool& result,int targetSum){
        if(result==true) return;
        sum+=root->val;
        if(root->left==nullptr && root->right==nullptr){
            if(sum==targetSum){
                result=true;
                return;
            }
        }
        if(root->left){
            process(root->left,sum,result,targetSum);
            sum-=root->left->val;
        }
        if(root->right){
            process(root->right,sum,result,targetSum);
            sum-=root->right->val;
        }
    }
};

不想写迭代。。。

113 路经总和II

回溯,存入每条路径

/**
 * 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<vector<int>> pathSum(TreeNode* root, int targetSum) {
        vector<vector<int>> result;
        if(root==nullptr) return result;
        vector<int> each;
        int sum=0;
        process(root, targetSum,each,sum, result);
        return result;
        
    }
    void process(TreeNode* root, int targetSum, vector<int>& each, int& sum, vector<vector<int>>& result){
        sum+=root->val;
        each.push_back(root->val);
        if(root->left==nullptr && root->right==nullptr){//叶节点
            if(sum==targetSum){
                result.push_back(each);
            }
            return;
        }
        if(root->left) {
            process(root->left,targetSum,each,sum,result);
            each.pop_back();
            sum-=root->left->val;
        }
        if(root->right){
            process(root->right,targetSum,each,sum,result);
            each.pop_back();
            sum-=root->right->val;
        }
    }
};

106. 从中序与后序遍历序列构造二叉树

思路:
中序遍历:左头右
后序遍历:左右头
先从后序遍历中找到头节点(最后一位)。
然后在中序遍历中找到头节点,左边是左子树,右边是右子树。
切割中序遍历得到左子树和右子树。(中序遍历版)
根据中序遍历的左子树的长度可以在后序遍历中从头开始得到左子树(后序遍历版)的长度。
把子树的两个遍历版再次递归。
递归终止条件:
后序遍历数组为空

好了

/**
 * 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* buildTree(vector<int>& inorder, vector<int>& postorder) {
        TreeNode* root=process(inorder,postorder);
        return root;
    }
    TreeNode* process(vector<int>& inorder, vector<int>& postorder){
        if(postorder.size()==0) return nullptr;
        TreeNode* root=new TreeNode(postorder[postorder.size()-1]);
        int index=0;
        int size_in=inorder.size();
        int size_post=postorder.size();
        for(int i=0;i<size_in;++i){
            if(inorder[i]==postorder[size_post-1]) {
                index=i;
                break;
            }
        }
        vector<int> inorder_left(inorder.begin(), inorder.begin() + index);
        vector<int> inorder_right(inorder.begin() + index+1,inorder.end());
        postorder.resize(postorder.size() - 1);//舍弃最后一位因为用过了
        vector<int> postorder_left(postorder.begin(),postorder.begin()+inorder_left.size());
        vector<int> postorder_right(postorder.begin()+inorder_left.size(),postorder.end());
        TreeNode* L=process(inorder_left,postorder_left);
        TreeNode* R=process(inorder_right,postorder_right);
        root->left=L;
        root->right=R;
        return root;
        
        
    }
};

需要二刷 很精妙的递归过程。

105. 从前序与中序遍历序列构造二叉树

前序:头左右
中序:左头右

/**
 * 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* buildTree(vector<int>& preorder, vector<int>& inorder) {
        TreeNode* root=process(preorder,inorder);
        return root;
    }
    TreeNode* process(vector<int>& preorder, vector<int>& inorder){
        if(preorder.size()==0) return nullptr;
        int pre_size=preorder.size();
        int in_size=inorder.size();
        TreeNode* root=new TreeNode(preorder[0]);
        int index=0;
        for(int i=0;i<in_size;++i){
            if(inorder[i]==preorder[0]){
                index=i;
                break;
            }
        }
        vector<int> in_left(inorder.begin(),inorder.begin()+index);
        vector<int> in_right(inorder.begin()+index+1,inorder.end());
        vector<int> pre_left(preorder.begin()+1,preorder.begin()+1+in_left.size());
        vector<int> pre_right(preorder.begin()+1+in_left.size(),preorder.end());
        TreeNode* L=process(pre_left,in_left);
        TreeNode* R=process(pre_right,in_right);
        root->left=L;
        root->right=R;
        return root;

    }
};

前序和中序可以唯一确定一棵二叉树。

后序和中序可以唯一确定一棵二叉树。

那么前序和后序可不可以唯一确定一棵二叉树呢?

前序和后序不能唯一确定一棵二叉树!,因为没有中序遍历无法确定左右部分,也就是无法分割。

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值