Day18_二叉树
16. 找树左下角的值
513. 找树左下角的值
思路1:递归法(前序遍历)
记录遍历到的最大深度,记录该深度下第一个遍历到的元素值,不断更新结果至遍历完所有的结点,即找到最大值。
class Solution {
public:
int MaxDepth = -1;
int result = INT_MAX;
void tranversal(TreeNode* root, int Depth) {
if (root->left == NULL && root->right == NULL) {
if (Depth > MaxDepth) { // 大于是为了保证最深层的result是最左结点的值
MaxDepth = Depth;
result = root->val;
}
return ;
}
if (root->left) tranversal(root->left, Depth + 1);
if (root->right) tranversal(root->right, Depth + 1);
return ;
}
int findBottomLeftValue(TreeNode* root) {
// 题目要求是至少有一个结点,即不存在第一节点为空的情况
tranversal(root, 0);
return result;
}
};
思路2:迭代法(层序遍历)
层序遍历记录每层的第一个元素,答案为最后一层的第一个元素
class Solution {
public:
int findBottomLeftValue(TreeNode* root) {
// 题目要求是至少有一个结点,即不存在第一节点为空的情况
int result;
queue<TreeNode*> que;
que.push(root);
while (!que.empty()) {
int que_size = que.size();
for (int i = 0; i < que_size; i++) {
TreeNode* node = que.front();
que.pop();
if (i == 0) result = node->val;
if (node->left) que.push(node->left);
if (node->right) que.push(node->right);
}
}
return result;
}
};
17. 路径总和
112. 路径总和
思路:
先序遍历,在叶子节点处判断路径和是否满足条件
class Solution {
public:
bool ans_flag = false;
void tranversal(TreeNode* root, int sum) {
if (ans_flag) return ;
if (root->left == NULL && root->right == NULL) { // 到叶子节点再判断是否满足
if (sum == 0) {
ans_flag = true;
}
return ;
}
if (root->left) tranversal(root->left, sum - root->left->val);
if (root->right) tranversal(root->right, sum - root->right->val);
}
bool hasPathSum(TreeNode* root, int targetSum) {
if (root == NULL) return false;
tranversal(root, targetSum - root->val);
return ans_flag;
}
};
精简递归的写法
class Solution {
public:
bool hasPathSum(TreeNode* root, int targetSum) {
if (root == NULL) return false;
if (!root->left && !root->right && targetSum == root->val) return true;
return hasPathSum(root->left, targetSum - root->val) | hasPathSum(root->right, targetSum - root->val);
}
};
利用栈模拟递归回溯
class Solution {
public:
// 先序遍历
bool hasPathSum(TreeNode* root, int targetSum) {
if (root == NULL) return false;
stack<pair<TreeNode*, int>> stk;
stk.push(pair<TreeNode*, int>(root, root->val));
while (!stk.empty()) {
pair<TreeNode*, int> node = stk.top();
stk.pop();
if (!node.first->left && !node.first->right && node.second == targetSum) return true; // 中
if (node.first->right) stk.push({node.first->right, node.second + node.first->right->val}); // 右
if (node.first->left) stk.push({node.first->left, node.second + node.first->left->val}); // 左
}
return false;
}
};
18. 从中序与后序遍历序列构造二叉树
根据中序和后续的遍历顺序特点,互相配合构造出二叉树
后续遍历 左 右 中,最后一个元素作为当前子树的根节点
中序遍历 左 中 右,子树的根结点左边为左子树值,右边为右子树值
反复递归划分区间,直到区间大小全部划分为1,回溯构造二叉树
class Solution {
private:
TreeNode* tranversal(vector<int> inorder, vector<int> postorder) {
if (postorder.size() == 0) return NULL;
// 后序遍历数组中的最后一个元素作为当前的子树的根
int root_value = postorder[postorder.size() - 1];
TreeNode* root = new TreeNode(root_value);
// 左右递归至只有一个元素,子树的建立完成
if (postorder.size() == 1) return root;
// 找到中序遍历的切割点
int divide_index;
for (int i = 0; i < inorder.size(); i++) {
if (inorder[i] == root_value) {
divide_index = i;
break;
}
}
// 切割中序遍历数组,左闭右开
vector<int> leftInorder(inorder.begin(), inorder.begin() + divide_index);
vector<int> rightInorder(inorder.begin() + divide_index + 1, inorder.end());
// posterorder 舍弃末尾元素
postorder.resize(postorder.size() - 1);
// 切割后续数组,左闭右开,由于遍历顺序导致中序和后续前一部分都是左子树的遍历结果,所以后续和中序划分方式相同
vector<int> leftPosterorder(postorder.begin(), postorder.begin() + divide_index);
vector<int> rightPosterorder(postorder.begin() + divide_index, postorder.end());
root->left = tranversal(leftInorder, leftPosterorder);
root->right = tranversal(rightInorder, rightPosterorder);
return root;
}
public:
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
if (inorder.size() == 0) return NULL;
return tranversal(inorder, postorder);
}
};