LeetCode 刷题 -- Day 8

今日题目

题目难度备注
404. 左叶子之和简单
513. 找树左下角的值简单
112. 路径总和简单
106. 从中序与后序遍历序列构造二叉树中等
654. 最大二叉树中等

题目:404. 左叶子之和

404. 左叶子之和 - 力扣(LeetCode)

一、源代码

class Solution {
private:
    int sum = 0;
    void DFS(TreeNode* root) {
        if (!root) return;
        if (root->left && !root->left->left && !root->left->right) {  // 左子树为叶子结点
            sum += root->left->val;
        }
        DFS(root->left);
        DFS(root->right);
    }
    
public:
    int sumOfLeftLeaves(TreeNode* root) {
        DFS(root);
        return sum;
    }
};

二、代码思路

​ DFS 遍历树,遇到左子树为叶子结点的,则将它左子树的值加入到 sum 中。


题目:513. 找树左下角的值

513. 找树左下角的值 - 力扣(LeetCode)

一、源代码

class Solution {
private:
    int mostDeepHight = -1,mostDeepVal = -1;
    
    void DFS(TreeNode* root, int h) {
        if (!root) return;
        if (!root->left && !root->right) {     // 遇到叶子结点进行判断
            if (h > mostDeepHight) {           // 当前结点深度更深,则更新。由于左结点优先,所以记录的为最左侧结点的值
                mostDeepHight = h;
                mostDeepVal = root->val;
            }
        }
        DFS(root->left, h + 1);                // 先访问左子树,保证左结点优先
        DFS(root->right, h + 1);
    }
    
public:
    int findBottomLeftValue(TreeNode* root) {
        DFS(root,0);
        return mostDeepVal;
    }
};

二、代码思路

​ 先序遍历树,利用 mostDeepHight 记录遍历过程中遇到的最大深度,mostDeepVal 记录遍历过程中遇到的最大深度的结点值。遍历时遇到叶子结点则进行判断,若该叶子结点的深度大于mostDeepHight 则更新 mostDeepHight 和mostDeepVal 。这样可得到最底层的结点。

​ 而利用先序遍历,先访问当前结点的左子树,再访问右子树,再加上 叶子结点的深度大于mostDeepHight 才更新(并非大于等于)这样就保证了对同一层结点,只记录最左边的结点值,即为答案。


题目:112. 路径总和

112. 路径总和 - 力扣(LeetCode)

一、源代码

class Solution {
private:
    bool hasSum = false;                            // 标志符号,存在则置为 true
    void DFS(TreeNode* root, int sum, int targetSum) {
        if (!root) return;
        sum += root->val;                            // 记录结点值之和
        
        if (!root->left && !root->right) {           // 遇到叶子结点时进行判断
            if (sum == targetSum) {
                hasSum = true;
                return;
            }
        }
        DFS(root->left,sum,targetSum);
        DFS(root->right,sum,targetSum); 
    }
    
public:
    bool hasPathSum(TreeNode* root, int targetSum) {
        DFS(root,0,targetSum);
        return hasSum;
    }
};

二、代码思路

​ DFS 遍历树同时记录路径的结点值之和(sum),若访问叶子结点时遇到 sum == targetSum,则把 hasSum 置为 true (初始化为false),最后返回 hasSum 即可。


题目:106. 从中序与后序遍历序列构造二叉树

106. 从中序与后序遍历序列构造二叉树 - 力扣(LeetCode)

一、源代码

class Solution {
    // 利用中序和后序序列性质,不断拆分 inorder 和 postorder 序列,每次选取一个要操作的序列,递归构造树
    // l1 为指向当前要操作的中序序列的最左端,r1 为最右端
    
    TreeNode* build(vector<int>& inorder, vector<int>& postorder, int l1,int r1,int l2, int r2) {
        if (l1 > r1) return nullptr;                 // 当左指针l1 > 右指针r1,说明非法,构造的结点为空,所以返回 nullptr
        TreeNode* root = new TreeNode;               // 一次构造一个结点
        root->val = postorder[r2];                   // 结点的值为要操作的postorder 序列的最右一个
        
        int i = l1;                                  
        for(;inorder[i] != root->val;i++);           // 找到 postorder[r2] 在 inorder 中的下标
        int llen = i - l1;                           // 左子树长度,即下一次要操作左序列长度
        int rlen = r1 - i;                           // 右子树长度,即下一次要操作右序列长度
        
        // 拆分 inorder,postorder,构造 root 的左右孩子
        root->left = build(inorder, postorder, l1, l1 + llen - 1, l2, l2 + llen -1);
        root->right = build(inorder,postorder,r1 - rlen + 1 , r1, r2 - rlen, r2 - 1);
        return root;
    }
    
public:
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        TreeNode* root =  build(inorder, postorder, 0, inorder.size() - 1, 0, postorder.size() - 1);
        return root;
    }
};

二、代码思路

​ 利用中序和后序序列性质,不断拆分 inorder 和 postorder 序列,每次选取一个要操作的序列,递归构造树。

​ ① 后序序列的最右侧的元素(假设为x),为树或子树的顶点。

​ ② 中序序列以 x 为中心,x 左侧的元素为 x 的左子树, x 右侧的元素为 x 的右子树。


题目:654. 最大二叉树

654. 最大二叉树 - 力扣(LeetCode)

一、源代码

class Solution {
private: 
    // 递归构建树,一次build 一个结点
    
    TreeNode* build(vector<int>& nums, int l, int r) {
        if (l > r) return nullptr;              // 非法则 返回空结点
        TreeNode* root = new TreeNode;
        int maxIndx = -1, maxVal = -1;
        
        for (int i = l; i <= r; i++) {          // 找到最大值 
            if (nums[i] > maxVal) {
                maxIndx = i;
                maxVal = nums[i];
            }
        }
        
        root->val = maxVal;                             // 用最大值构建结点 和左右孩子
        root->left = build(nums, l, maxIndx - 1);       
        root->right = build(nums, maxIndx + 1, r);
        return root;
    }
    
public:
    TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
        return build(nums, 0, nums.size() - 1);
    }
};

二、代码思路

​ 递归构建树,一次 build 一个结点,利用左右指针(l,r)不断拆分数组。每次只处理 l … … . r 之间的序列,从中选取最大值构建结点,并更新左右指针,构建左右子树。

  • 46
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值