day 18 第六章 二叉树 part05

总结

关键是递归逻辑的书写,要明确前中后序遍历的逻辑,套进递归里

● 513.找树左下角的值

/*513. 找树左下角的值
    中等
给定一个二叉树的 根节点 root,请找出该二叉树的 最底层 最左边 节点的值。
假设二叉树中至少有一个节点。*/

class Solution_513 {
 public:
  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) {}
  };

  /*
   * 层序遍历用的是队列,头节点就是该层最左节点,只需判断是否为最后一层
   */
  int findBottomLeftValue(TreeNode *root) {
      int res = 0;
      if (!root)
          return res;
      queue<TreeNode *> record;
      record.push(root);
      while (!record.empty()) {
          int size = record.size();
          int count = 0;
          for (int i = 0; i < size; ++i) {
              TreeNode *node = record.front();
              record.pop();
              if (i == 0)
                  res = node->val;
              if (node->left)
                  record.push(node->left);
              if (node->right)
                  record.push(node->right);
          }
      }
      return res;
  }
};

● 112. 路径总和

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



class Solution_112 {
 public:
  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) {}
  };
  /*递归函数:返回值为根节点到叶子节点的高度是否等于指定值,输入参数为当前节点,指定值,路径和
终止条件:当前节点为叶子节点时,判断和是否相等,返回结果
递归逻辑:
前序遍历,中左右
1.和加上当前节点值
2.判断终止条件
3.递归左右节点*/
  bool getPathSum(TreeNode *node, int targetSum, int path_sum) {
      path_sum += node->val;
      if (!node->left && !node->right) {
          return path_sum == targetSum;
      }
      bool left_res{false};
      bool right_res{false};
      if (node->left)
          left_res = getPathSum(node->left, targetSum, path_sum);
      if (node->right)
          right_res = getPathSum(node->right, targetSum, path_sum);
      return (left_res | right_res);
  }

  bool hasPathSum(TreeNode *root, int targetSum) {

      if(!root)
          return false;
      int sum = 0;
      return getPathSum(root, targetSum, sum);
  }
};

113.路径总和ii

/*113. 路径总和 II
中等
    给你二叉树的根节点 root 和一个整数目标和 targetSum ,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。
叶子节点 是指没有子节点的节点。*/

class Solution_113 {
 public:
  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) {}
  };

  /*递归函数:返回值无,输入参数为当前节点,指定值,当前路径数组,结果数组
      终止条件:当前节点为叶子节点时,判断和是否相等,如果相等结果数组添加当前路径数组
      递归逻辑:前序遍历,中左右
  1.当前路径数组加上当前节点值
  2.判断终止条件
  3.递归左右节点,注意输入参数均为引用,当前路径数组递归之后需要弹出最后一个节点,回溯到中节点,从而避免一个路径数组中记录了左右两个不可能同时到达的子节点
   */
  void get_path(TreeNode *node, int targetSum,vector<int> &cur_path, vector<vector<int>> &res){
      cur_path.push_back(node->val);
      if (!node->left && !node->right) {
          int path_sum = 0;
          for(auto i : cur_path){
              path_sum += i;
          }
          if(path_sum == targetSum){
              res.push_back(cur_path);
          }
          return;
      }
      if (node->left) {
          get_path(node->left, targetSum, cur_path, res);
          cur_path.pop_back();//回溯到中节点
      }
      if (node->right) {
          get_path(node->right, targetSum, cur_path, res);
          cur_path.pop_back();//回溯到中节点
      }
      return;
  }

  vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
      vector<vector<int>> res;
      if(!root)
          return res;
      vector<int> path;
      get_path(root, targetSum, path, res);
      return res;
  }
};

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

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

 提示:

1 <= inorder.length <= 3000
postorder.length == inorder.length
-3000 <= inorder[i], postorder[i] <= 3000
inorder 和 postorder 都由 不同 的值组成
postorder 中每一个值都在 inorder 中
inorder 保证是树的中序遍历
postorder 保证是树的后序遍历
 */

class Solution_106 {
 public:
  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) {}
  };

  /*
   * 输入参数为两个遍历数组,返回结果为根节点
终止条件为遍历数组剩一个元素,那需要保证传入参数不为空
单层递归逻辑:
先判断终止条件,若终止,返回根节点
先取后序数组最后一个元素作为根节点
通过该节点切割中序数组
根据切割得到的左右中序数组数量切割后序数组
左子树遍历,输入为左中序数组,左后序数组,返回为左子节点
右子树遍历,输入为右中序数组,右后序数组,返回为右子节点
返回根节点
   */

  TreeNode *build_tree(vector<int> &inorder, vector<int> &postorder) {
      //先取后序数组最后一个元素作为根节点
      TreeNode *root = new TreeNode(*(postorder.end() - 1));
      //终止条件为遍历数组剩一个元素,那需要保证传入参数不为空
      if (inorder.size() == 1) {
          return root;
      }
      //通过该节点切割中序数组
      int mid_index = 0;
      while (mid_index < inorder.size()) {
          if (inorder[mid_index] == root->val)
              break;
          mid_index += 1;
      }
      vector<int> inorder_left(inorder.begin(), inorder.begin() + mid_index);//注意去掉已经用过的根节点
      vector<int> inorder_right(inorder.begin() + mid_index + 1, inorder.end());

      //根据切割得到的左右中序数组数量切割后序数组
      vector<int> postorder_left(postorder.begin(), postorder.begin() + inorder_left.size());
      vector<int> postorder_right(postorder.begin() + inorder_left.size(), postorder.end() - 1);//注意去掉已经用过的根节点

      //左子树遍历,需要保证传入参数不为空
      if (inorder_left.empty())
          root->left = nullptr;
      else
          root->left = build_tree(inorder_left, postorder_left);

      //右子树遍历,需要保证传入参数不为空
      if (inorder_right.empty())
          root->right = nullptr;
      else
          root->right = build_tree(inorder_right, postorder_right);

      return root;

  }

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

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

/*105. 从前序与中序遍历序列构造二叉树
    中等
给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。*/

class Solution_105 {
 public:
  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) {}
  };
  /*
   * 输入参数为两个遍历数组,返回结果为根节点
终止条件为遍历数组剩一个元素,那需要保证传入参数不为空
单层递归逻辑:
先判断终止条件,若终止,返回根节点
先取前序数组第一个元素作为根节点
通过该节点切割中序数组
根据切割得到的左右中序数组数量切割前序数组
左子树遍历,输入为左中序数组,左前序数组,返回为左子节点
右子树遍历,输入为右中序数组,右前序数组,返回为右子节点
返回根节点
   */
  TreeNode *build(vector<int> &preorder, vector<int> &inorder){
      //先取后序数组最后一个元素作为根节点
      TreeNode *root = new TreeNode(*(preorder.begin()));
      //终止条件为遍历数组剩一个元素,那需要保证传入参数不为空
      if (inorder.size() == 1) {
          return root;
      }
      //通过该节点切割中序数组
      int mid_index = 0;
      while (mid_index < inorder.size()) {
          if (inorder[mid_index] == root->val)
              break;
          mid_index += 1;
      }
      vector<int> inorder_left(inorder.begin(), inorder.begin() + mid_index);//注意去掉已经用过的根节点
      vector<int> inorder_right(inorder.begin() + mid_index + 1, inorder.end());

      //根据切割得到的左右中序数组数量切割中序数组
      vector<int> preorder_left(preorder.begin() + 1, preorder.begin() + inorder_left.size() + 1);//注意去掉已经用过的根节点
      vector<int> preorder_right(preorder.begin() + inorder_left.size() + 1, preorder.end());

      //左子树遍历,需要保证传入参数不为空
      if (inorder_left.empty())
          root->left = nullptr;
      else
          root->left = build(preorder_left, inorder_left);

      //右子树遍历,需要保证传入参数不为空
      if (inorder_right.empty())
          root->right = nullptr;
      else
          root->right = build(preorder_right, inorder_right);

      return root;
  }

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

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

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1. 什么是二叉树? 二叉树是一种树形数据结构,其中每个节点最多有两个子节点,分别称为左子节点和右子节点。 2. 什么是二叉搜索树? 二叉搜索树是一种特殊的二叉树,其中左子节点的值小于等于父节点的值,右子节点的值大于等于父节点的值。 3. 什么是完全二叉树? 完全二叉树是一种特殊的二叉树,除了最后一层外,每一层都必须填满,且最后一层从左到右依次填入节点。 4. 什么是平衡二叉树? 平衡二叉树是一种特殊的二叉搜索树,其左右子树高度差不超过1。 5. 什么是二叉树的遍历? 二叉树的遍历是指按照某种顺序依次访问二叉树中的每个节点,常见的遍历方式包括前序遍历、中序遍历和后序遍历。 6. 什么是二叉树的前序遍历? 二叉树的前序遍历是指按照根节点、左子树、右子树的顺序依次访问二叉树中的每个节点。 7. 什么是二叉树的中序遍历? 二叉树的中序遍历是指按照左子树、根节点、右子树的顺序依次访问二叉树中的每个节点。 8. 什么是二叉树的后序遍历? 二叉树的后序遍历是指按照左子树、右子树、根节点的顺序依次访问二叉树中的每个节点。 9. 什么是二叉树的层序遍历? 二叉树的层序遍历是指按照从上到下、从左到右的顺序依次访问二叉树中的每个节点。 10. 如何判断一个二叉树是否为二叉搜索树? 可以通过中序遍历得到二叉树中所有节点的值,然后判断这些值是否按照升序排列即可判断是否为二叉搜索树。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值