513. 找树左下角的值
思路1:
先序遍历二叉树,每到达一个更深的层,更新第一次遇到的节点。
class Solution {
public:
int findBottomLeftValue(TreeNode* root) {
preorder(root, 0);
return ans;
}
private:
int ans, depth = -1;
void preorder(TreeNode *root, int depth) {
if (root == NULL) return ;
if (this->depth < depth) {
this->depth = depth;
ans = root->val;
}
preorder(root->left, depth + 1);
preorder(root->right, depth + 1);
}
};
思路2:
层序遍历,每到一个新的层将第一个节点的值更新为答案。
class Solution {
public:
int findBottomLeftValue(TreeNode* root) {
preorder(root, 0);
return ans;
}
private:
int ans, depth = -1;
void preorder(TreeNode *root, int depth) {
if (root == NULL) return ;
if (this->depth < depth) {
this->depth = depth;
ans = root->val;
}
preorder(root->left, depth + 1);
preorder(root->right, depth + 1);
}
};
112. 路径总和
思路1: 递归
在每个叶子节点处查看当前路径的总和。
class Solution {
public:
bool hasPathSum(TreeNode* root, int targetSum) {
return preorder(root, 0, targetSum);
}
private:
bool preorder(TreeNode *root, int sum, int targetSum) {
if (root == NULL) return false;
if (!root->left && !root->right) { // 遇到叶子节点
if (sum + root->val == targetSum) return true;
else return false;
}
return preorder(root->left, sum + root->val, targetSum)
|| preorder(root->right, sum + root->val, targetSum);
}
};
思路2: 迭代法
思路同上
class Solution {
public:
bool hasPathSum(TreeNode* root, int targetSum) {
if (root == NULL) return false;
stack<pair<TreeNode *, int>> stk;
stk.push({root, root->val});
while (!stk.empty()) {
pair<TreeNode *, int> node = stk.top(); stk.pop();
if (!node.first->left && !node.first->right) { // 叶子节点
if (node.second == targetSum) return true;
}
if (node.first->left) stk.push({node.first->left, node.second + node.first->left->val});
if (node.first->right) stk.push({node.first->right, node.second + node.first->right->val});
}
return false;
}
};
附加一题:
113. 路径总和 II
思路:
到记录每条路径上的节点值,遇到叶子节点,如果路径值之和等于目标值,则将该路径加入结果。
class Solution {
public:
vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
vector<vector<int>> result;
if (root == NULL) return result;
vector<int> path;
path.push_back(root->val);
preorder(root, targetSum - root->val, result, path);
return result;
}
private:
void preorder(TreeNode *root, int targetSum, vector<vector<int>> &result, vector<int> &path) {
if (!root->left && !root->right) {
if (targetSum == 0) result.push_back(path);
return ;
}
if (root->left) {
path.push_back(root->left->val);
preorder(root->left, targetSum - root->left->val, result, path);
path.pop_back();
}
if (root->right) {
path.push_back(root->right->val);
preorder(root->right, targetSum - root->right->val, result, path);
path.pop_back();
}
}
};
106. 从中序与后序遍历序列构造二叉树
思路:
后续遍历的最后一个元素是根节点(之后为每棵子树的根节点)
利用该节点将中序遍历结果划分为左右子树的中序遍历结果
根据该节点的左子树的中序遍历结果可以得到左子树的节点个数,就可以将后续遍历结果划分为左右子树
再对左右子树递归上面的过程。
class Solution {
public:
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
if (inorder.size() == 0) return NULL;
return buildTree(inorder, postorder, 0, inorder.size(), 0, postorder.size());
}
private:
TreeNode *buildTree(vector<int> &inorder, vector<int> &postorder, int Ibegin, int Iend, int Pbegin, int Pend) {
if (Ibegin == Iend) return NULL;
TreeNode *root = new TreeNode(postorder[Pend - 1]);
if (Pend - Pbegin == 1) return root;
int diveIndex;
for (diveIndex = Ibegin; diveIndex < Iend; diveIndex++) {
if (inorder[diveIndex] == root->val) break;
}
// 切割中序数组
// 左中序数组,左闭右开
int leftIbegin = Ibegin;
int leftIend = diveIndex;
// 右中序数组,左闭右开
int rightIbegin = diveIndex + 1;
int rightIend = Iend;
// 切割后续数组
// 左后续数组
int leftPbegin = Pbegin;
int leftPend = leftPbegin + diveIndex - Ibegin;
// 右后续数组
int rightPbegin = leftPend;
int rightPend = Pend - 1;
root->left = buildTree(inorder, postorder, leftIbegin, leftIend, leftPbegin, leftPend);
root->right = buildTree(inorder, postorder, rightIbegin, rightIend, rightPbegin, rightPend);
return root;
}
};