题目链接:513.找树左下角的值、112.路径总和、113.路径总和ii、106.从中序与后序遍历序列构造二叉树、105.从前序与中序遍历序列构造二叉树
文章链接:代码随想录
二叉树
1. 找树左下角的值
(待更新...)
//迭代法(由于层序遍历是按层遍历的,只需要获取最后一行的第一个节点值即可)
class Solution {
public:
int findBottomLeftValue(TreeNode* root) {
queue<TreeNode*> que;
int result = 0;
que.push(root); //题目保证二叉树至少有一个节点,因此可以不判断根节点是否为空
while(!que.empty()) {
int size = que.size();
for(int i = 0; i < 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;
}
};
//递归法(本题意在寻找深度最大的最靠左的叶子节点,因此优先左遍历,由于不需要对中间节点处理,因此前中后序遍历都可以,保证左遍历优先即可)
//注意:深度最大的最靠左的叶子节点不一定就是左孩子
class Solution {
public:
//定义全局变量
int maxDepth = INT_MIN; //最大深度
int result = 0; //最大深度最靠左的节点值
void traversal(TreeNode* root, int depth) {
//终止条件:遍历到叶子节点,判断当前叶子节点的深度是否为最大深度,如果是,则更新result和maxDepth
if(root -> left == nullptr && root -> right == nullptr) {
if(depth > maxDepth) {
result = root -> val;
maxDepth = depth;
}
return;
}
//左遍历
//代码整体可精简为traversal(root -> left, depth + 1);
if(root -> left) {
depth++;
traversal(root -> left, depth);
depth--; //回溯,深度-1
}
//右遍历
//代码整体可精简为traversal(root -> left, depth + 1);
if(root -> right) {
depth++;
traversal(root -> right, depth);
depth--; //回溯,深度-1
}
return;
}
int findBottomLeftValue(TreeNode* root) {
int depth = 0;
traversal(root, depth);
return result;
}
};
2. 路径总和
(待更新...)
//递归法
class Solution {
private:
bool traversal(TreeNode* cur, int count) {
//终止条件:遇到叶子节点
//如果计数器已减为0,说明该路径所有节点值相加与目标和相等,返回true;否则返回false
if(cur -> left == nullptr && cur -> right == nullptr && count == 0) return true;
if(cur -> left == nullptr && cur -> right == nullptr && count != 0) 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;
}
public:
bool hasPathSum(TreeNode* root, int targetSum) {
if(root == nullptr) return false;
return traversal(root, targetSum - root -> val); //目标值减去根节点值,结果作为函数参数,作用是计数器
}
};
//迭代法
//队列中的每一个元素既要记录节点指针,又要记录从头节点到该节点的路径数值总和
//因此,利用Pair结构来存放队列中的元素
//定义为:pair<Treenode*, int>(节点指针,路径数值)
class Solution {
public:
bool hasPathSum(TreeNode* root, int targetSum) {
if(root == nullptr) return false;
//队列中存放的是pair<Treenode*, int>
queue<pair<TreeNode*, int>> que;
que.push(pair<TreeNode*, int>(root, root -> val));
while(!que.empty()) {
pair<TreeNode*, int> node = que.front();
que.pop();
//如果遍历到叶子节点且该节点所记录的路径数值等于目标值,则直接返回true
if(!node.first -> left && !node.first -> right && node.second == targetSum)
return true;
//记录左孩子节点,除了存放左孩子节点指针,还要存放该节点所对应的路径数值
if(node.first -> left)
que.push(pair<TreeNode*, int>(node.first -> left, node.second + node.first -> left -> val));
//记录右孩子节点,除了存放右孩子节点指针,还要存放该节点所对应的路径数值
if(node.first -> right)
que.push(pair<TreeNode*, int>(node.first -> right, node.second + node.first -> right -> val));
}
return false;
}
};
3. 路径总和ii
(待更新...)
//递归法(基于“112.路径总和”的代码实现基础)
class Solution {
private:
//全局变量:result存放结果,path存放单条路径
vector<vector<int>> result;
vector<int> path;
//递归需要遍历整个二叉树,因此不需要返回值
void traversal(TreeNode* cur, int count) {
//当遍历到叶子节点且找到路径数值为targetSum路径,将该路径存入结果
if(!cur -> left && ! cur -> right && count == 0) {
result.push_back(path);
return;
}
//当遍历到叶子节点但该路径不满足条件,直接返回
if(!cur -> left && !cur -> right && count != 0) return;
//左遍历
if(cur -> left) {
path.push_back(cur -> left -> val);
traversal(cur -> left, count - cur -> left -> val); //这里既有递归又有回溯
path.pop_back(); //回溯
}
//右遍历
if(cur -> right) {
path.push_back(cur -> right -> val);
traversal(cur -> right, count - cur -> right -> val); //这里既有递归又有回溯
path.pop_back(); //回溯
}
return;
}
public:
vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
result.clear();
path.clear();
if(root == nullptr) return result;
path.push_back(root -> val); //先存入根节点
traversal(root, targetSum - root -> val);
return result;
}
};
4. 从中序与后序遍历序列构造二叉树
(待更新...)
5. 从前序与中序遍历序列构造二叉树
(待更新...)
相关题目和后续提高: