题目:513.找树左下角的值
文章链接:代码随想录
视频链接:LeetCode:513.找树左下角的值
题目链接:力扣题目链接
解法1:迭代遍历,一直取每层的第一个数,如果有新的一层则重新覆盖就是最底层的左节点
class Solution {
public:
int findBottomLeftValue(TreeNode* root) {
// 创建队列,存放二叉树指针
queue<TreeNode* > que;
// 判断根节点是否为空,不为空则放进元素
if(root != NULL) que.push(root);
// 返回结果
int result = 0;
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;
}
};
解法2:递归
class Solution {
public:
int MAX_Depth = INT32_MIN; // 最大深度
int result;
// 不需要返回值
void traversal(TreeNode* node, int depth){ // depth 为当前的层数
// 终止条件,碰到叶子节点
if(node->left == NULL && node->right == NULL){
if(depth > MAX_Depth){
MAX_Depth = depth; // 更新最大深度
result = node->val; // 更新结果
}
return ;
}
// 因为在叶子节点就终止,所以需要判断左右孩子是否为空
// 处理的逻辑也跟遍历差不多,如果同层会优先遍历左子数,
// 这时候已经给MAX_Depth更新层数了,如果没有更深层时,就不会再对结果更新。
if(node->left != NULL){
depth++; // 0->1
traversal(node->left,depth); // [1]
depth--; // 回溯
}
if(node->right != NULL){
depth++;
traversal(node->right,depth);
depth--; // 回溯
}
return;
}
int findBottomLeftValue(TreeNode* root) {
traversal(root, 0);
return result;
}
};
题目:112. 路径总和 、113.路径总和ii
文章链接:代码随想录
视频链接:LeetCode:112. 路径总和 、113.路径总和ii
解法1:
class Solution {
public:
bool reversal(TreeNode* node, int count){
// 遍历的叶子节点就终止
if(node->left == NULL && node->right == NULL){
// 用相减的方式判断是否达到目标值
if(count == 0) return true;
else{
return false;
}
}
// 左,在叶子节点终止,照例判断是否为空
if(node->left != NULL){
count -= node->left->val; // 因为当进入下一层递归的时候直接判断count是否为空了,所以要在递归上层对值进行处理
if(reversal(node->left,count)) return true; // 如果返回true 则说明找到了,向上进行返回
count += node->left->val; // 回溯,再把值加回来
// 精简到一起, 传入的是count-node->left->val,count值并没有改变,遍历另一条路径的时候相减又是其他的值
// if(reversal(node->left,count-node->left->val)) return true;
}
if(node->right != NULL){
count -= node->right->val;
if(reversal(node->right,count)) return true;
count += node->right->val; // 回溯
}
return false;
}
bool hasPathSum(TreeNode* root, int targetSum) {
if (root == NULL) return false;
return reversal(root, targetSum-root->val);
}
};
解法2:
class Solution {
public:
vector<vector<int>> result;
vector<int> path;
void reversal(TreeNode*node, int count){
if(!node->left && !node->right && count==0) {
result.push_back(path); // 把路径放到结果数组里
return;
}
if (!node->left && !node->right) return ; // 遇到叶子节点而没有找到合适的边,直接返回
// 左
if(node->left){
// 把数组放入路径中
path.push_back(node->left->val);
count -= node->left->val;
reversal(node->left, count); // 递归
count += node->left->val; // 回溯
path.pop_back(); // 回溯
}
if(node->right){
// 把数组放入路径中
path.push_back(node->right->val);
count -= node->right->val;
reversal(node->right, count); // 递归
count += node->right->val; // 回溯
path.pop_back(); // 回溯
}
return;
}
vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
result.clear(); // 保证结果数组里为空的
path.clear();
if(root == NULL) return result;
path.push_back(root->val); // 把根节点放入,常忘记
reversal(root, targetSum-root->val); // 目标值减去根节点的值
return result;
}
};
题目:106.从中序与后序遍历序列构造二叉树、105.从前序与中序遍历序列构造二叉树
文章链接:代码随想录
视频链接:LeetCode:106.从中序与后序遍历序列构造二叉树口
解法1:
106.从中序与后序遍历序列构造二叉树
class Solution {
public:
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 delimiterInder; // delimiterInder==1
for(delimiterInder=0; delimiterInder<inorder.size(); delimiterInder++){
if(inorder[delimiterInder] == rootValue) break; // 退出循环
}
// 第四步:切割中序数组,得到 中序左数组和中序右数组
// 左闭右开区间:[0,delimiterInder) [0,1)
vector<int> leftInorder(inorder.begin(),inorder.begin()+delimiterInder); // [9]
vector<int> rightInorder(inorder.begin()+delimiterInder+1, inorder.end()); // +1 第delimiterInder个元素不要
// 第五步:切割后序数组,得到 后序左数组和后序右数组
// 先去除掉最后一个元素
postorder.resize(postorder.size()-1); // 进行一个缩减
// 左闭右开,注意这里使用了左中序数组大小作为切割点:[0, leftInorder.size)
vector<int> leftPostorder(postorder.begin(), postorder.begin() + leftInorder.size());
// [leftInorder.size(), end)
vector<int> rightPostorder(postorder.begin() + leftInorder.size(), postorder.end());
// 第六步
root->left = traversal(leftInorder,leftPostorder);
root->right = traversal(rightInorder,rightPostorder);
return root;
}
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
if (inorder.size() == 0 || postorder.size() == 0) return NULL;
return traversal(inorder, postorder);
}
};
105.从前序与中序遍历序列构造二叉树
class Solution {
public:
TreeNode* traversal(vector<int>& preorder, vector<int>& inorder){
// 第一步 如果后序数组为空,则说明到叶子节点了
if(preorder.size() == 0) return NULL;
// 第二步,遍历前序数组的第一个元素作为分割点
int rootValue = preorder[0];
TreeNode* root = new TreeNode(rootValue); //创建二叉树节点
// 叶子节点, 分割后可能没有元素,可能只剩一个,也可能剩很多
if(preorder.size() == 1) return root;
// 第三步,找分割点
int delimiterInder; // delimiterInder==1
for(delimiterInder=0; delimiterInder<inorder.size(); delimiterInder++){
if(inorder[delimiterInder] == rootValue) break; // 退出循环
}
// 第四步:切割中序数组,得到 中序左数组和中序右数组
// 左闭右开区间:[0,delimiterInder) [0,1)
vector<int> leftInorder(inorder.begin(),inorder.begin()+delimiterInder); // [9]
vector<int> rightInorder(inorder.begin()+delimiterInder+1, inorder.end()); // +1 第delimiterInder个元素不要
// 第五步:切割前序数组,得到 前序左数组和前序右数组
// 左闭右开,注意这里使用了左中序数组大小作为切割点:[1, leftInorder.size+1) 不要第一个元素
vector<int> leftPreorder(preorder.begin()+1, preorder.begin() + 1 + leftInorder.size());
// [leftInorder.size()+1, end)
vector<int> rightPreorder(preorder.begin() + 1 + leftInorder.size(), preorder.end());
// 第六步
root->left = traversal(leftPreorder,leftInorder);
root->right = traversal(rightPreorder,rightInorder);
return root;
}
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
if (inorder.size() == 0 || preorder.size() == 0) return NULL;
return traversal(preorder,inorder);
}
};