代码随想录训练营16day:二叉树5

一、513. 找树左下角的值

递归法:主要是需要理解深度怎么计算,以及最大深度的保存。

/**
 1 递归方式

 需要找到最大的深度 + 回溯
 **/
//  int maxdepth = INT_MIN;
//  int result = 0;
void transDepth(struct TreeNode* cur, int depth, int* maxdepth, int* result)
{
    if(cur->left == NULL && cur->right == NULL)
    {
       if(*maxdepth < depth)
       {
          *maxdepth = depth;
          *result = cur->val;
          printf("val = %d\n", *result);
       }
       return;
    }

    if(cur->left)
    {
        depth++;
        transDepth(cur->left, depth, maxdepth, result);
        depth--;
    }

    if(cur->right)
    {
        depth++;
        transDepth(cur->right, depth, maxdepth, result);
        depth--;
    }
    return;
} 

int findBottomLeftValue(struct TreeNode* root) {

     if(root == NULL)
       return 0;
     int maxdepth = INT_MIN;
     int result = 0;
     transDepth(root, 0, &maxdepth, &result);
     return result;
}    

二、112. 路径总和

本题需要理解到递归过程,什么时候需要返回值,另外,这种遍历所有或者在所有节点中搜索的题目,应该都需要回溯。

bool  judge(struct TreeNode* root, int targetSum)
{
   //递归过程
    if(!root->left && !root->right && (targetSum) == 0)
       return true;
    if(!root->left && !root->right)
       return false;
    
    /**需要回溯**/
    if(root->left)
    {
        targetSum -= root->left->val;
        bool left_ret = judge(root->left, targetSum);
        if(left_ret)
           return true;
        targetSum = targetSum + root->left->val;
    }

    if(root->right)
    {
        targetSum -= root->right->val;
        bool right_ret = judge(root->right, targetSum);
        if(right_ret)
           return true;
        targetSum = targetSum + root->right->val;
    }

    return false;
}
bool hasPathSum(struct TreeNode* root, int targetSum) {
    if(root == NULL)
      return false;//空树
    
    return judge(root, targetSum - root->val);
}

 用迭代法时候,填value值时候出现错误,是想去找top的上一个值,然后相加,结果就是在遍历过程,top可能会减到-1,然后再加回来,导致数组越界。

bool hasPathSum(struct TreeNode* root, int targetSum) {
    if(root == NULL)
      return false;//空树
    
    //return judge(root, targetSum - root->val);

    /**迭代法**/
    //用两个数组来模拟栈
    int top = -1;

    struct TreeNode** NodeStk = (struct TreeNode**)malloc(sizeof(struct TreeNode*) * 5001);
    int* nums = (int*)malloc(sizeof(int) * 5001);

    /**入栈**/
    NodeStk[++top] = root;
    nums[top] = root->val;
    
    /**遍历栈区**/
    while(top > -1)
    {
       //出栈
       struct TreeNode* curNode = NodeStk[top];
       int curvalue = nums[top];
       //printf("nums = %d\n", curvalue);
       top--;
       //判断
       if(!curNode->left && !curNode->right && (curvalue == targetSum))
       {
          return true;
       }

       /**右子节点**/
       int nums_pre_indx = top;
       if(curNode->right)
       {
          nums[++top] = curvalue + curNode->right->val;
          NodeStk[top] = curNode->right;   
       }

       if(curNode->left)
       {
          nums[++top] = curvalue + curNode->left->val;
          NodeStk[top] = curNode->left;
       }

    }
    return false;
}

三、113 路径总和II

该题思路也是递归+回溯,根据代码随想录上面的思路,如下:

做该题使用遇到两个难点:

1)第一就是malloc时候,把returnsize和returncolSize放到递归函数里面,这样导致了参数过多,借鉴其他人的写法,可以使用全局变量,减少函数参数;

2)就是最后处理时候,应该memcpy到result里面。

 int** result;
 int* path;
 int reSize ;
 int* recolSize;
 int path_idx;
 void trans(struct TreeNode* curNode, int num)
 {
     if(!curNode->left && !curNode->right && (num == 0))
     {
        int* tmp = (int*)malloc(sizeof(int) * path_idx);
        memcpy(tmp, path, sizeof(int) * (path_idx));
        result[reSize] = tmp;
        recolSize[(reSize)++] = path_idx;
        return;
     }

    if(!curNode->left && !curNode->right)
    {
        return;
    }
    //printf("indx = %d\n", path_idx);
    if(curNode->left)
    {
      path[(path_idx)++] = curNode->left->val;
      num = num - curNode->left->val;
      trans(curNode->left, num);
      num = num + curNode->left->val;
      (path_idx)--;
    }

    if(curNode->right)
    {
      path[(path_idx)++] = curNode->right->val;
      num = num - curNode->right->val;
      trans(curNode->right, num);
      num = num + curNode->right->val;
      (path_idx)--;
    }
   
 }

int** pathSum(struct TreeNode* root, int targetSum, int* returnSize, int** returnColumnSizes) {
    //先使用路径总和1题目里面的迭代方式
    if(root == NULL)
      return NULL;//空树
    reSize = 0;//代表有多少种路径
    recolSize = (int*)calloc(2000, sizeof(int));//每一种路径里面 包含多少个节点
    result = (int**)malloc(sizeof(int*) * 2000);
    path = (int*) malloc(sizeof(int) * 5000);
    path_idx = 0;
    path[path_idx++] = root->val;
    trans(root, targetSum - root->val);
    *returnColumnSizes = recolSize;
    *returnSize = reSize;
    return result;
}

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

可以根据代码随想录的讲解思路进行解答,但是,在code过程还是遇到一些问题:

1 递归函数的参数设定:一开始就是思考的是就是用原函数,不用增加参数,但是这样递归时候,左区间和右区间并不能区分;

2 递归函数怎么实现:递归的时候,中序遍历的左区间和后序的左区间,得到左子树;右子树同理;

3 每一层申请新的root节点时候,初始化时候val和左右节点都需要初始化好,之前测试时候,left和right没有指向NULL,导致异常。

4 区间封闭原则需要注意!!

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
 struct TreeNode* build(int* inorder, int inorderSize, int inorder_start, int inorder_end,
  int* postorder, int postorderSize, int postorder_start, int postorder_end)
 {
    if (postorder_start == postorder_end)
      return NULL;
    //先找后序节点的最后一个,是头结点
    int rootvalue = postorder[postorder_end -1];
    struct TreeNode* root = (struct TreeNode*)malloc(sizeof(struct TreeNode));
    root->val = rootvalue;//postorder[postorder_end -1];//这个是头结点
    root->left = NULL;
    root->right = NULL;//先初始化!!
    if(postorder_end - postorder_start == 1)
    {
        return root;//只有一个节点的情况
    }
    int inorder_left_s = 0, inorder_left_e = 0;
    int inorder_right_s =0, inorder_right_e = 0;

    int postorder_left_s = 0, postorder_left_e = 0;
    int postorder_right_s = 0, postorder_right_e = 0;

    int middle_pos = 0;
    /**分割中序数组:左右数组**/
    for(middle_pos  = inorder_start; middle_pos < inorder_end; middle_pos++)
    {
       if(inorder[middle_pos] == rootvalue)
       {
          break;
       }
    }
    /**分开中序:左闭右开**/
    inorder_left_s = inorder_start;
    inorder_left_e = middle_pos;//

    inorder_right_s = middle_pos + 1;
    inorder_right_e = inorder_end;

    /**分割后序数组:左闭右开**/
    postorder_left_s = postorder_start;
    postorder_left_e = postorder_start + middle_pos - inorder_start;

    postorder_right_s = postorder_start + middle_pos - inorder_start;
    postorder_right_e = postorder_end -1; //最后一个元素排除了


 
    root->left  = build(inorder, inorderSize, inorder_left_s, inorder_left_e, postorder, postorderSize, postorder_left_s, postorder_left_e);
    root->right  = build(inorder, inorderSize, inorder_right_s, inorder_right_e, postorder, postorderSize, postorder_right_s, postorder_right_e);
   
    return root;
 }
struct TreeNode* buildTree(int* inorder, int inorderSize, int* postorder, int postorderSize) {
    //inorder是中序 postorder是后序
    if(inorderSize == 0 || postorderSize == 0)
    {
        return NULL;//没有值
    }
    return build(inorder, inorderSize, 0, inorderSize, postorder, postorderSize, 0 , postorderSize);
}

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

需要注意以下几点:

1 前序遍历是首位置是头结点;

2 拆分前序遍历的左右区间时候,记得排除首位置元素,另外,起始位置也是改变了的。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */

 struct TreeNode* build(int* preorder, int preorderSize, int preorder_start, int preorder_end,
  int* inorder, int inorderSize, int inorder_start, int inorder_end)
 {
    if (preorder_start == preorder_end)//切分到位置相等处 说明没有节点了
      return NULL;
    //先找前序节点的第一个,是头结点
    int rootvalue = preorder[preorder_start];
    struct TreeNode* root = (struct TreeNode*)malloc(sizeof(struct TreeNode));
    root->val = rootvalue;//postorder[postorder_end -1];//这个是头结点
    root->left = NULL;
    root->right = NULL;//先初始化!!
    if(preorder_end - preorder_start == 1)
    {
        return root;//只有一个节点的情况
    }
    int inorder_left_s = 0, inorder_left_e = 0;
    int inorder_right_s =0, inorder_right_e = 0;

    int preorder_left_s = 0, preorder_left_e = 0;
    int preorder_right_s = 0, preorder_right_e = 0;

    int middle_pos = 0;
    /**分割中序数组:左右数组**/
    for(middle_pos  = inorder_start; middle_pos < inorder_end; middle_pos++)
    {
       if(inorder[middle_pos] == rootvalue)
       {
          break;
       }
    }
    /**分开中序:左闭右开**/
    inorder_left_s = inorder_start;
    inorder_left_e = middle_pos;//

    inorder_right_s = middle_pos + 1;
    inorder_right_e = inorder_end;

    /**分割前序序数组:左闭右开**/
    preorder_left_s = preorder_start + 1;//第一个元素是头节点 排除
    //preorder_start + 1是起始位置 , middle_pos - inorder_start是Size
    preorder_left_e = preorder_start + 1 + middle_pos - inorder_start;

    preorder_right_s = preorder_start + 1 + middle_pos - inorder_start;
    preorder_right_e = preorder_end; 


 
    root->left  = build(preorder, preorderSize, preorder_left_s, preorder_left_e, inorder, inorderSize, inorder_left_s, inorder_left_e);
    root->right  = build(preorder, preorderSize, preorder_right_s, preorder_right_e, inorder, inorderSize, inorder_right_s, inorder_right_e);
   
    return root;
 }

struct TreeNode* buildTree(int* preorder, int preorderSize, int* inorder, int inorderSize) {
    if(preorderSize == 0 || inorderSize == 0)
    {
        return NULL;
    }
    return build(preorder, preorderSize, 0, preorderSize, inorder, inorderSize, 0 , inorderSize);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值