Day18 二叉树:找树左下角的值、路径总和、从中序与后序遍历序列构造二叉树
力扣相关例题
513. 找树左下角的值
给定一个二叉树的 根节点 root,请找出该二叉树的 最底层 最左边 节点的值。
假设二叉树中至少有一个节点。
示例 :
输入: root = [2,1,3]
输出: 1
class Solution {
public:
int result; // 全局变量 最大深度最左节点的数值
int maxdepth = INT_MIN; // 全局变量 记录最大深度
void traveltree(TreeNode* node, int depth) {
if (node->left == NULL && node->right == NULL) {
if (depth > maxdepth) {
maxdepth = depth;
result = node->val;
}
return ;
}
//这边一定是先左后右,因为是找左下角的值
if (node->left != NULL) {
depth++;
traveltree(node->left, depth);
depth--;
}
if (node->right != NULL) {
depth++;
traveltree(node->right,depth);
depth--;
}
return ;
}
int findBottomLeftValue(TreeNode* root) {
traveltree(root, 0);
return result;
}
};
112. 路径总和
给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true ;否则,返回 false 。
叶子节点 是指没有子节点的节点。
示例 :
输入:root = [5,4,8,11,null,13,4,7,2,null,null,null,1], targetSum = 22
输出:true
解释:等于目标和的根节点到叶节点路径如上图所示。
class Solution {
public:
bool traveltree(TreeNode* root, int sum) {
// 叶子结点 且 路径和 等于 目标值
if (root->left == NULL && root->right == NULL && sum == 0) {
return true;
}
// 叶子结点 且 路径和 不等于 目标值
if (root->left == NULL && root->right == NULL) {
return false;
}
// 左子树遍历
if (root -> left) {
sum -= root->left->val;
if (traveltree(root->left, sum)) {
return true;
}
sum += root->left->val; //回溯
}
// 右子树遍历
if (root -> right) {
sum -= root->right->val;
if (traveltree(root->right, sum)) {
return true;
}
sum += root->right->val; //回溯
}
return false;
}
bool hasPathSum(TreeNode* root, int targetSum) {
// 这道题是在递归之前就减去当前要递归结点的值,所以才判断是否等于0
if (root == NULL) {
return false;
}
return traveltree(root, targetSum - root->val);
}
};
106. 从中序与后序遍历序列构造二叉树(重点)
给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。
示例 1:
输入:inorder = [9,3,15,20,7], postorder = [9,15,7,20,3]
输出:[3,9,20,null,null,15,7]
解题步骤:
- 如果数组大小为零的话,说明是空节点了。
- 如果不为空,那么取后序数组最后一个元素作为节点元素。
- 找到后序数组最后一个元素在中序数组的位置,作为切割点
- 切割中序数组,切成中序左数组和中序右数组 (顺序别搞反了,一定是先切中序数组)
- 切割后序数组,切成后序左数组和后序右数组
- 递归处理左区间和右区间
class Solution {
public:
TreeNode* traveltree(vector<int>& inorder, vector<int>& postorder) {
// 第一步:如果数组大小为零的话,说明是空节点了
if (postorder.size() == 0) {
return NULL;
}
// 第二步:如果不为空,那么取后序数组最后一个元素作为节点元素
int rootval = postorder[postorder.size() - 1];
TreeNode* root = new TreeNode(rootval);
// 叶子结点
if (postorder.size() == 1) {
return root;
}
// 第三步:找到后序数组最后一个元素在中序数组的位置,作为切割点
int index;
for (index = 0; index < inorder.size(); index++) {
if (inorder[index] == rootval) {
break;
}
}
// 第四步:切割中序数组,切成中序左数组和中序右数组 (顺序别搞反了,一定是先切中序数组)(左闭右开)
//[0, index) [index+1, end)
vector<int> leftinorder(inorder.begin(), inorder.begin() + index);
vector<int> rightinorder(inorder.begin() + index + 1, inorder.end());
// 第五步:切割后序数组,切成后序左数组和后序右数组(左闭右开)
postorder.resize(postorder.size() - 1); //舍弃末尾结点元素!
//[0, leftinorder.size) [leftinorder, end)
vector<int> leftpostorder(postorder.begin(), postorder.begin() + leftinorder.size());
vector<int> rightpostorder(postorder.begin() + leftinorder.size(), postorder.end());
// 第六步:递归处理左区间和右区间
root->left = traveltree(leftinorder, leftpostorder);
root->right = traveltree(rightinorder, rightpostorder);
return root;
}
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
if (inorder.size() == 0 || postorder.size() == 0) {
return NULL;
}
return traveltree(inorder, postorder);
}
};