解题思路
原题链接:513. 找树左下角的值
解题思路
要找到最底层的最左边元素,首先要确定深度最大的子树,然后找到其最左边的叶子结点(也就是最后一层的第一个结点)。
一、迭代法:层序遍历
层序遍历最适合解本题,因层序遍历是按成遍历,因此,最后一次遍历的一定为最后一层,记录遍历最后一层的第一个元素即为最底层的最左边叶子。
/**
* Definition for a binary tree node.
* 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) {}
* };
*/
class Solution {
public:
int findBottomLeftValue(TreeNode* root) {
int res = 0;
queue<TreeNode*> que;
que.push(root);
while(!que.empty()) {
int n = que.size();
res = que.front()->val;
while(n--) {
TreeNode* node = que.front(); que.pop();
if(node->left) que.push(node->left);
if(node->right) que.push(node->right);
}
}
return res;
}
};
二、递归法:回溯
想要找到最后一层的最左端叶子,需要计算两个东西。第一,需要计算出最大深度,第二需要计算出最后一层的第一个叶子。设置一个maxDepth
记录最大深度,设置一个res
记录结果。
若当前遍历的深度比之前已记录的最大深度更大,则记录当前的叶子结点。在遍历时,按照先遍历左,后遍历右的顺序。这样子既可以保证最后一层第一次记录的应为最左端的叶子,又可以保证最底层就算在右端的最右侧,也可以进行记录。
回溯变量展开写
/**
* Definition for a binary tree node.
* 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) {}
* };
*/
class Solution {
public:
int maxDepth = 0, res = 0;
void traversal(int depth, TreeNode* root) {
// 遇到叶子结点且为深度更大,则记录
if(!root->left && !root->right) {
if(depth > maxDepth) {
maxDepth = depth;
res = root->val;
return ;
}
}
// 这里先左后右,可保证,第一个记录的一定为做底层的最左边叶子
if(root->left) {
depth++;
traversal(depth , root->left);
depth--; // 回溯后要回退,选择下一种情况操作
}
// 最底层的最左边叶子有可能是位于右结点
if(root->right) {
depth++;
traversal(depth, root->right);
depth--;
}
}
int findBottomLeftValue(TreeNode* root) {
traversal(1,root);
return res;
}
};
精简depth
/**
* Definition for a binary tree node.
* 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) {}
* };
*/
class Solution {
public:
int maxDepth = 0, res = 0;
void traversal(int depth, TreeNode* root) {
// 遇到叶子结点且为深度更大,则记录
if(!root->left && !root->right) {
if(depth > maxDepth) {
maxDepth = depth;
res = root->val;
return ;
}
}
// 这里先左后右,可保证,第一个记录的一定为做底层的最左边叶子
if(root->left) {
traversal(depth + 1, root->left);
}
// 最底层的最左边叶子有可能是位于右结点
if(root->right) {
traversal(depth + 1, root->right);
}
}
int findBottomLeftValue(TreeNode* root) {
traversal(1,root);
return res;
}
};
这种写法在传入dpeth时,利用了栈压入的特性,并不会修改不改变原depth的值并且在后续遍历中还可以用到原元素。
参考文章:513.找树左下角的值