训练营打卡Day18
文章目录
题45:513. 找树左下角的值
思路(递归法)
- 在遍历树的过程中记录每个叶子节点的深度
- 如果发现当前叶子节点的深度比之前记录的最大深度还大,就更新最大深度并记录当前叶子节点的值。
- 最后返回记录最左下角叶子节点的值。
使用递归的方法来遍历整棵树
- 在函数traversal中,如果当前节点没有左子节点和右子节点,那么它就是一个叶子节点。如果当前节点的深度大于之前记录的最大深度,就更新最大深度并记录当前节点的值。
- 否则,如果当前节点有左子节点,就递归调用 traversal 函数,并将左子节点作为参数,深度加 1。
- 如果当前节点有右子节点,就递归调用 traversal 函数,并将右子节点作为参数,深度加 1。
在函数 findBottomLeftValue 中,调用 traversal 函数,并以根节点作为参数,深度设为 0 开始遍历整棵树。
代码(递归法)
class Solution {
public:
int maxDep = INT_MIN;
int ans;
void traversal(TreeNode* node, int depth)
{
if(!node->left && !node->right)
{
if(maxDep < depth)
{
maxDep = depth;
ans = node->val;
}
return;
}
if(node->left)
{
traversal(node->left, depth+1);
}
if(node->right)
{
traversal(node->right, depth+1);
}
}
int findBottomLeftValue(TreeNode* root) {
traversal(root, 0);
return ans;
}
};
思路(迭代法)
- 使用一个队列来保存当前需要访问的节点
- 从根节点开始,将根节点入队。
- 只要队列不为空,就取出队首节点,并将其左子节点和右子节点加入队尾。
- 当遍历完一层的节点时,就记录当前队首节点的值。
- 重复3和4,直到队列为空
在循环中,每次取出队首节点,并将其左子节点和右子节点加入队尾。如果当前节点是当前层的第一个节点,就记录当前节点的值。
代码(迭代法)
class Solution {
public:
int findBottomLeftValue(TreeNode* root) {
if(!root) return -1;
queue<TreeNode*>que;
que.push(root);
int ans;
while(!que.empty())
{
int n = que.size();
for(int i = 0; i < n; i++)
{
auto node = que.front();
que.pop();
if(node->left) que.push(node->left);
if(node->right) que.push(node->right);
if(i == 0) ans = node->val;
}
}
return ans;
}
};
题46:112. 路径总和
思路
- 使用递归的方式遍历整棵树
- 在遍历过程中,如果当前节点是叶子节点,并且它的值等于目标值,就返回true.
- 否则,如果当前节点有左子节点,就递归调用traversal函数,并将左子节点作为参数,目标值减去当前节点的值。
- 如果当前节点有右子节点,就递归调用traversal函数,并将右子节点作为参数,目标值减去当前节点的值。
- 如果上述步骤均不成立,就返回false。
在函数hasPathSum中,调用traversal函数,并以根节点作为参数,目标值作为参数开始遍历整棵树。最后,返回traversal函数的返回值,表示是否找到了符合要求的路径。
代码
class Solution {
public:
bool traversal(TreeNode* node, int targetSum)
{
if(!node->left && !node->right && targetSum == node->val)
return true;
if(node->left && traversal(node->left, targetSum - node->val))
return true;
if(node->right && traversal(node->right, targetSum - node->val))
return true;
return false;
}
bool hasPathSum(TreeNode* root, int targetSum) {
if(!root) return false;
return traversal(root, targetSum);
}
};
题47:106. 从中序与后序遍历序列构造二叉树
思路
- 如果后序遍历序列为空,就返回NULL。
- 否则,从后续遍历中取出最后一个元素,作为当前节点的值。
- 如果后序遍历序列只包含一个元素,就返回当前节点。
- 否则,在中序遍历序列中查找当前节点的值。
- 将中序遍历序列分为当前节点左边和右边两个部分,分别对应当前节点的左子树和右子树。
- 将后序遍历序列也分为两个部分,分别对应左子树和右子树。
- 递归地调用buildTree函数,分别构建左子树和右子树。
- 返回当前节点
代码
class Solution {
public:
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
if(postorder.size() == 0) return NULL;
int rootVal = postorder[postorder.size()-1];
TreeNode *node = new TreeNode(rootVal);
if(postorder.size() == 1) return node;
int index = 0;
while(index < inorder.size())
{
if(inorder[index] == rootVal) break;\
index++;
}
vector<int>leftIn(inorder.begin(), inorder.begin()+index);
vector<int>rightIn(inorder.begin()+index+1, inorder.end());
vector<int>leftPost(postorder.begin(), postorder.begin()+leftIn.size());
vector<int>rightPost(postorder.begin()+leftIn.size(), postorder.end()-1);
node->left = buildTree(leftIn, leftPost);
node->right = buildTree(rightIn, rightPost);
return node;
}
};