代码随想录第十八天|Leetcode513.找树左下角的值、Leetcode112. 路径总和、Leetcode113. 路径总和ii、Leetcode106.从中序与后序遍历重建树、DFS模板总结

代码随想录第十八天|Leetcode513.找树左下角的值、Leetcode112. 路径总和、Leetcode113. 路径总和ii、Leetcode106.从中序与后序遍历序列构造二叉树、Leetcode105.从前序与中序遍历序列构造二叉树

Leetcode513.找树左下角的值

遍历太熟悉了,完全通畅一遍过

class Solution {
public:
    int findBottomLeftValue(TreeNode* root) {
        int result;
        queue<TreeNode*> que;
        que.push(root);
        while(!que.empty()){
            int size=que.size();
            result=que.front()->val;
            for(int i=0;i<size;i++){
                TreeNode* temp=que.front();
                que.pop();
                if(temp->left) que.push(temp->left);
                if(temp->right) que.push(temp->right);
            }
        }
        return result;
    }
};

DFS不太适合这道题,不过也得会

class Solution {
public:
    void dfs(TreeNode* cur,int& result,int curHeight,int& maxHeight){
        if(cur==NULL) return;
        curHeight++;
        dfs(cur->left,result,curHeight,maxHeight);
        dfs(cur->right,result,curHeight,maxHeight);
        if(curHeight>maxHeight){//对首次达到最深处的值进行保存
            maxHeight=curHeight;
            result=cur->val;
        }
    }
    int findBottomLeftValue(TreeNode* root) {
        int result=0;
        int curHeight=0;
        int maxHeight=0;
        dfs(root,result,curHeight,maxHeight);
        return result;
    }
};

Leetcode112. 路径总和

简直是DFS的代表性题目,非常值得二刷

二刷提醒

class Solution {
public:
    bool hasPathSum(TreeNode* root, int targetSum) {
        if(root==NULL) return false;
        if(root->left==NULL&&root->right==NULL) return targetSum==root->val; //到达叶子结点
        return hasPathSum(root->left,targetSum-root->val) || hasPathSum(root->right,targetSum-root->val);//这太精髓了
    }
};

Leetcode113. 路径总和ii

二刷提醒

由于path是临时变量,在结束一整套递归后,恰好会在return时清零释放掉,避免了自己写清零逻辑的混乱。

class Solution {
private:
    vector<vector<int>> result;
    void dfs(TreeNode* root, int targetSum,vector<int> path){
        if(root==NULL) return;
        targetSum-=root->val;
        path.push_back(root->val);
        if(root->left==NULL&&root->right==NULL&&targetSum==0){
            result.push_back(path);
            return;//path自动清零
        }
        if(root->left) dfs(root->left,targetSum,path);
        if(root->right) dfs(root->right,targetSum,path);
    }
public:
    vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
        vector<int> path;
        dfs(root,targetSum,path);
        return result;
    }
};

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

注意

  1. 数组拷贝构造为左闭右开区间[start,end)
  2. 一定要自己先用注释梳理好逻辑再写
class Solution {
private:
    TreeNode* treversal(vector<int>& inorder, vector<int>& postorder){
        //如果为空,直接return
        if(postorder.size()==0) return NULL;
        //必须做的事
        int value=postorder[postorder.size()-1];
        TreeNode* cur=new TreeNode(value);
        //结束逻辑,如果为1直接返回
        if(postorder.size()==1) return cur;
        //切割中序遍历
        int i;
        for(i=0;i<inorder.size();i++){//找到切割位置
            if(inorder[i]==cur->val) break;
        }
        vector<int>inorderLeft(inorder.begin(),inorder.begin()+i);
        vector<int>inorderRight(inorder.begin()+i+1,inorder.end());
        //切割后序遍历
        vector<int>postorderLeft(postorder.begin(),postorder.begin()+inorderLeft.size());
        vector<int>postorderRight(postorder.begin()+inorderLeft.size(),postorder.end()-1);
        //递归赋值给左右子树
        cur->left=treversal(inorderLeft,postorderLeft);
        cur->right=treversal(inorderRight,postorderRight);
        //递归结束的return
        return cur;
    }
public:
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        TreeNode* root = treversal(inorder,postorder);
        return root;
    }
};

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

跟上道题一模一样,一遍过直接一个字都没错

class Solution {
private:
    TreeNode* treversal(vector<int>& preorder, vector<int>& inorder){
        //如果为空,直接返回
        if(preorder.size()==0) return NULL;
        //生成当前节点
        TreeNode* cur=new TreeNode(preorder[0]);
        //如果为1,直接返回当前节点
        if(preorder.size()==1) return cur;
        //找到根的位置
        int i=0;
        for(i=0;i<inorder.size();i++){
            if(inorder[i]==preorder[0]) break;
        }
        //切割中序遍历
        vector<int>inorderLeft(inorder.begin(),inorder.begin()+i);
        vector<int>inorderRight(inorder.begin()+i+1,inorder.end());
        //切割先序遍历
        vector<int>preorderLeft(preorder.begin()+1,preorder.begin()+1+inorderLeft.size());
        vector<int>preorderRight(preorder.begin()+1+inorderLeft.size(),preorder.end());
        //给左右子树赋值
        cur->left=treversal(preorderLeft,inorderLeft);
        cur->right=treversal(preorderRight,inorderRight);
        //返回当前节点
        return cur;
    }
public:
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        TreeNode* root=treversal(preorder,inorder);
        return root;
    }
};

总结DFS模板

自顶向下寻找路径

一般路径

由于path是临时变量,在结束一整套递归后,恰好会在return时清零释放掉,避免了自己写清零逻辑的混乱。

vector<vector<int>>res;
void dfs(TreeNode*root,vector<int>path)
{
    if(root==NULL) return;  //根节点为空直接返回
    path.push_back(root->val);  //做必须做的事
    if(!root->left && !root->right) //结束逻辑  
    {
        res.push_back(path);
        return;
    }
    dfs(root->left,path); //到这说明结束逻辑没生效,那就继续递归
    dfs(root->right,path);
}

目标和路径targetsum

  1. 由于path是临时变量,在结束一整套递归后,恰好会在return时清零释放掉,避免了自己写清零逻辑的混乱。时刻牢记时刻牢记
  2. 不用新增一个临时变量cursum来判断当前路径和,只需要用目标和targetsum减去节点值,最终结束条件判断target==0即可
void dfs(TreeNode*root, int targetsum, vector<int> path)
{
    if (root==NULL) return;//根节点为空直接返回
    targetsum-= root->val;       //做必须做的事
    path.push_back(root->val);
    if (!root->left && !root->right && targetsum == 0)//结束逻辑
    {
        res.push_back(path);
        return;
    }
    dfs(root->left, targetsum, path);//到这说明结束逻辑没生效,那就继续递归
    dfs(root->right, targetsum, path);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值