今天是第十八天,二叉树进入到比较难的部分了,需要更好地理解递归和回溯
513. 找树左下角的值
这道题的话用层序遍历会很容易,就遍历到最后一层然后最左边的值就行
class Solution {
public:
int findBottomLeftValue(TreeNode* root) {
queue<TreeNode*>que;
if(root != NULL)que.push(root);
int res = 0;
while(!que.empty()){
int size = que.size();
for(int i = 0; i < size; i++){
TreeNode*node = que.front();
que.pop();
if(i == 0)res = node->val;
if(node->left)que.push(node->left);
if(node->right)que.push(node->right);
}
}
return res;
}
};
当然,用递归也可以做,只是复杂一些
每一步的递归和回溯都要想清楚
class Solution {
public:
//int类型的最小值
int maxDepth = INT_MIN;
int result;
void find(TreeNode*root, int depth){
if(root->left == NULL && root->right == NULL){
//更新最大深度
if(depth > maxDepth){
maxDepth = depth;
//保存数值
result = root->val;
}
}
if(root->left){
depth++;
find(root->left,depth);
//--是回溯的步骤
depth--;
}
if(root->right){
depth++;
find(root->right,depth);
depth--;
}
}
int findBottomLeftValue(TreeNode* root) {
find(root, 0);
return result;
}
};
112. 路径总和
递归三部曲
类型:我们函数定义成bool类型,因为我们不需要返回深度什么之类的,传入参数就是当前节点和目标数值
终止条件:到达叶结点停止,也就是左右节点都为空的时候
单层逻辑:依次往下遍历,记得回溯即可
这里代码比较复杂,不够简洁,但可以更好地体现出回溯的过程
class Solution {
public:
bool traversal(TreeNode* cur, int count){
if(!cur->left && !cur->right && count == 0)return true;
if(!cur->left && !cur->right)return false;
if(cur->left){
//又+又-就是回溯的过程
count -= cur->left->val;
if(traversal(cur->left, count))return true;
count += cur->left->val;
}
if(cur->right){
count -=cur->right->val;
if(traversal(cur->right, count))return true;
count += cur->right->val;
}
return false;
}
bool hasPathSum(TreeNode* root, int targetSum) {
if(root == NULL)return 0;
return traversal(root, targetSum - root->val);
}
};
106. 从中序与后序遍历序列构造二叉树
第一步:如果数组大小为零的话,说明是空节点了。
第二步:如果不为空,那么取后序数组最后一个元素作为节点元素。
第三步:找到后序数组最后一个元素在中序数组的位置,作为切割点
第四步:切割中序数组,切成中序左数组和中序右数组 (顺序别搞反了,一定是先切中序数组)
第五步:切割后序数组,切成后序左数组和后序右数组
第六步:递归处理左区间和右区间
TreeNode* traversal (vector<int>& inorder, vector<int>& postorder) {
// 第一步
if (postorder.size() == 0) return NULL;
// 第二步:后序遍历数组最后一个元素,就是当前的中间节点
int rootValue = postorder[postorder.size() - 1];
TreeNode* root = new TreeNode(rootValue);
// 叶子节点
if (postorder.size() == 1) return root;
// 第三步:找切割点
int delimiterIndex;
for (delimiterIndex = 0; delimiterIndex < inorder.size(); delimiterIndex++) {
if (inorder[delimiterIndex] == rootValue) break;
}
// 第四步:切割中序数组,得到 中序左数组和中序右数组
// 第五步:切割后序数组,得到 后序左数组和后序右数组
// 第六步
root->left = traversal(中序左数组, 后序左数组);
root->right = traversal(中序右数组, 后序右数组);
return root;
}