代码随想录算法训练营第十八天| 513.找树左下角的值(做完层序遍历做)、112. 路径总和 、113.路径总和ii、106.从中序与后序遍历序列构造二叉树 、105.从前序与中序遍历序列构造二叉树

目录

513. 找树左下角的值

112. 路径总和

113. 路径总和 II

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

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


513. 找树左下角的值

等我掌握广搜的时候来填上这个坑!

112. 路径总和

题目描述:

给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true ;否则,返回 false 。

简单题目有简单的道理!自上而下路径总和的值不断减去当前根节点的值,直到叶子节点。

bool hasPathSum(struct TreeNode *root, int sum) {
    if(root==NULL)   return false;
    //没有叶子结点->判断根节点值是否等于目标值
    if(root->left==NULL&&root->right==NULL){
        return sum==root->val;
    }
    //选择当前根节点,目标值-根节点值,遍历左右
    int num=sum-root->val;
    return hasPathSum(root->left,num)||hasPathSum(root->right,num);
}

113. 路径总和 II

题目描述:给你二叉树的根节点 root 和一个整数目标和 targetSum ,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。

 写完回溯来写的这道题目,就容易一点。应该说回溯就是深搜!

最值得注意的一点区别是:收割结果之后不return,这是因为只有到空结点才做return操作,哪怕是叶子节点都要做当前结点值是否与目标值相等的判断。

而且不回溯!(只是说和回溯模板的区别)

int** ret;
int ret_num;
int* path;
int path_num;
int* len;

void backtracking(struct TreeNode* root,int targetSum){
    if(root==NULL)  return ;
    //先把根节点值加进去
    path[path_num++]=root->val;
    targetSum-=(root->val);
    //root为叶子节点时终止
    if(root->left==NULL&&root->right==NULL){
        //root的值=0时收割结果
        if(targetSum==0){
            int* temp=(int*)malloc(sizeof(int)*path_num);
            for(int i=0;i<path_num;i++){
                temp[i]=path[i];
            }
            len[ret_num]=path_num;
            ret[ret_num++]=temp;
        }
    }
    //递归左右(不需要回溯,不return,二叉树自上向下遍历,也就回不去)
    backtracking(root->left,targetSum);
    backtracking(root->right,targetSum);
    path_num--;
}
int** pathSum(struct TreeNode* root, int targetSum, int* returnSize, int** returnColumnSizes){
    ret=(int**)malloc(sizeof(int*)*1000);
    path=(int*)malloc(sizeof(int)*4000);
    len=(int**)malloc(sizeof(int*)*1000);
    ret_num=path_num=0;
    backtracking(root,targetSum);
    *returnSize=ret_num;
    *returnColumnSizes=(int*)malloc(sizeof(int)*ret_num);
    for(int i=0;i<ret_num;i++){
        (*returnColumnSizes)[i]=len[i];
    }
    return ret;
}

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

题目描述:

给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。

 思路很好想的,对于递归我很迷惑!

有一个问题:为什么在判断如果数组中只有一个元素,也就是树中只可能是一个根节点的时候,返回这个节点的话会报错?代码如下,报错也如下:

//找到当前根节点在中序遍历中的下标
int find_sign(int* inorder,int inorderSize,int target){
    for(int i=0;i<inorderSize;i++){
        if(inorder[i]==target){
            return i;
        }
    }
    return -1;
}

struct TreeNode* buildTree(int* inorder, int inorderSize, int* postorder, int postorderSize){
    //后序数组为空,表示根节点都没有,返回空
    if(postorderSize==0)    return NULL;
    struct TreeNode* root=(struct TreeNode*)malloc(sizeof(struct TreeNode));
    root->val=postorder[postorderSize-1];
    //后续数组只有一个元素,说明只有一个根节点,返回这个根节点
    // if(postorderSize==1)    return root;
    //找到根节点在中序遍历中的下标
    int index=find_sign(inorder,inorderSize,root->val);
    //右子树大小
    int rightSize=inorderSize-index-1;
    root->left=buildTree(inorder,index,postorder,index);
    root->right=buildTree(inorder+index+1,rightSize,postorder+index,rightSize);
    return root;
}

 解答:root结点没有对left和right做初始化导致报错,正确代码应该加上root->left=root->right=NULL的代码,正确的整体代码如下:

//找到当前根节点在中序遍历中的下标
int find_sign(int* inorder,int inorderSize,int target){
    for(int i=0;i<inorderSize;i++){
        if(inorder[i]==target){
            return i;
        }
    }
    return -1;
}

struct TreeNode* buildTree(int* inorder, int inorderSize, int* postorder, int postorderSize){
    //后序数组为空,表示根节点都没有,返回空
    if(postorderSize==0)    return NULL;
    struct TreeNode* root=(struct TreeNode*)malloc(sizeof(struct TreeNode));
    root->val=postorder[postorderSize-1];
    root->left=root->right=NULL;
    //后续数组只有一个元素,说明只有一个根节点,返回这个根节点
    if(postorderSize==1)    return root;
    //找到根节点在中序遍历中的下标
    int index=find_sign(inorder,inorderSize,root->val);
    //右子树大小
    int rightSize=inorderSize-index-1;
    root->left=buildTree(inorder,index,postorder,index);
    root->right=buildTree(inorder+index+1,rightSize,postorder+index,rightSize);
    return root;
}

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

和上个题目如出一辙。

注意函数传递参数中数组的位置!

struct TreeNode* buildTree(int* preorder, int preorderSize, int* inorder, int inorderSize){
    //前序数组为空,表示根节点都没有,返回空
    if(preorderSize==0)    return NULL;
    struct TreeNode* root=(struct TreeNode*)malloc(sizeof(struct TreeNode));
    root->val=preorder[0];
    root->left=root->right=NULL;
    //前序数组只有一个元素,说明只有一个根节点,返回这个根节点
    if(preorderSize==1)    return root;
    //找到根节点在中序遍历中的下标
    int index=find_sign(inorder,inorderSize,root->val);
    //右子树大小
    int rightSize=inorderSize-index-1;
    root->left=buildTree(preorder+1,index,inorder,index);
    root->right=buildTree(preorder+index+1,rightSize,inorder+index+1,rightSize);
    return root;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值