代码随想录DAY18 513.找树左下角的值112. 路径总和 113. 路径总和ii 106. 从中序与后序遍历序列构造二叉树105. 从前序与中序遍历序列构造二叉树

513.找树左下角的值

就是找最下面的左叶子

使用层序遍历,因为层序遍历使用的时队列,所以头部的元素(i==0)是最左侧的

class Solution {
public:
    int findBottomLeftValue(TreeNode* root) {
        int res=0;
        queue<TreeNode*> que;
        if(root!=nullptr){
            que.push(root);
        } 

        while(!que.empty()){
            int size=que.size();
            for(int i=0;i<size;i++){
                TreeNode* node=que.front();
                if(i==0) res=node->val;
                que.pop();
                if(node->left) que.push(node->left);
                if(node->right) que.push(node->right);
            }
        }

        return res;
    }
};

112. 路径总和 

其实也是遍历

得走到目标节点的根节点(上一个节点)才能判断

递归:

递归结束条件:

走到叶子节点&&得到相应总值 返回ture。若走到叶子节点但没有得到相应总值 返回false。

若不是叶子节点,继续递归

递归过程:

首先减去根节点的左子树值,判断其左子树是否符合条件(即再次进入递归)符合条件 返回true

不符合条件 根节点的值恢复原样(就当没来过左子树)

右子树重复上述过程

class Solution {
public:
    bool traversal(TreeNode* root, int count){
        if(!root->left&&!root->right&&count==0) return true;
        if(!root->left&&!root->right) return false;

        if(root->left){
            count-=root->left->val;
            if(traversal(root->left,count)) return true;
            //为什么要撤销处理结果???
            //回到原来最初的模样
            count+=root->left->val;
        }

        if(root->right){
            count-=root->right->val;
            if(traversal(root->right,count)) return true;
            count+=root->right->val;
        }
        return false;
    }

    bool hasPathSum(TreeNode* root, int targetSum) {
        if(root==nullptr) return false;
        //为什么是targetSum-root->val
        //这里判断根节点
        return traversal(root,targetSum-root->val);
    }
};

非递归

就是遍历,遍历过程中记录路径之和

使用pair

class Solution {
public:
//注意pair的语法
    bool hasPathSum(TreeNode* root, int targetSum) {
        stack<pair<TreeNode*,int>> st;
        if(root!=nullptr){
            st.push(pair(root,root->val));
        }

        while(!st.empty()){
            pair<TreeNode*,int> node=st.top();
            st.pop();
            if(!node.first->left&&!node.first->right&&targetSum==node.second){
                return true;
            }

            if(node.first->right){
                st.push(pair<TreeNode*,int>(node.first->right,node.second+node.first->right->val));
            }

            if(node.first->left){
                st.push(pair<TreeNode*,int>(node.first->left,node.second+node.first->left->val));
            }

        }

        return false;
    }
};

113. 路径总和ii 

递归法

将路径记录下来就行了

问题:

为什么写成private????

class Solution {
private:
    vector<vector<int>> result;
    vector<int> path;
    void transfer(TreeNode* root, int sum){
        if(!root->left&&!root->right&&sum==0){
            result.push_back(path);
            return;
        }
        if(!root->left&&!root->right) return ;

        if(root->left){
            path.push_back(root->left->val);
            sum-=root->left->val;
            transfer(root->left,sum);
            path.pop_back();
            sum+=root->left->val;
        }

        if(root->right){
            path.push_back(root->right->val);
            sum-=root->right->val;
            transfer(root->right,sum);
            path.pop_back();
            sum+=root->right->val;
        }
    }

public:
    vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
        result.clear();
        path.clear();
        if(root==nullptr) return result;
        path.push_back(root->val);
        transfer(root,targetSum-root->val);

        return result;
    }
};

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

后序遍历确定根节点,分割中序遍历

中序遍历找出左右子树的节点数,分割后序遍历

 //9,3,15,20,7
 //9,15,7,20,3
//依照postorder的最后一个数字分割inorder

//舍弃末尾元素

 //9, 3, 15,20,7
 //9, 15,7,20,
 //依照刚刚分割好的

class Solution {
private:
    TreeNode* transfer(vector<int>& inorder, vector<int>& postorder){
        if(postorder.size()==0) return nullptr;

        //后序遍历最后一个数
        int num=postorder[postorder.size()-1];
        TreeNode* root=new TreeNode(num);
        postorder.pop_back();

        //分割inorder
        int inmid=0;
        for(;inmid<inorder.size();inmid++){
            if(inorder[inmid]==root->val) break;
        }

        vector<int> inorderLeft(inorder.begin(),inorder.begin()+inmid);
        vector<int> inorderRight(inorder.begin()+inmid+1,inorder.end());

        //分割postorder
        vector<int> postorderLeft(postorder.begin(),postorder.begin()+inorderLeft.size());
        vector<int> postorderRight(postorder.begin()+inorderLeft.size(),postorder.end());

        root->left=transfer(inorderLeft,postorderLeft);
        root->right=transfer(inorderRight,postorderRight);

        return root;
    }

public:
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        if(inorder.size()==0||postorder.size()==0) return nullptr;
        return transfer(inorder,postorder);
    }
};

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

与上文同理

class Solution {
private:
    TreeNode* transfer(vector<int>& preorder, vector<int>& inorder) {
        if(preorder.size()==0) return nullptr;

        TreeNode*root=new TreeNode(preorder[0]);
        preorder.erase(preorder.begin());

        //分割中序
        int midroot=0;
        for(;midroot<inorder.size();midroot++){
            if(inorder[midroot]==root->val) break;
        }

        vector<int> inorderLeft(inorder.begin(),inorder.begin()+midroot);
        vector<int> inorderRight(inorder.begin()+midroot+1,inorder.end());

        //分割前序
        vector<int> preorderLeft(preorder.begin(),preorder.begin()+inorderLeft.size());
        vector<int> preorderRight(preorder.begin()+inorderLeft.size(),preorder.end());
       
       root->left=transfer(preorderLeft,inorderLeft);
       root->right=transfer(preorderRight,inorderRight);

        return root;
    }

public:
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        if(preorder.size()==0||inorder.size()==0) return nullptr;
        return transfer(preorder,inorder);
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值