【LeetCode刷题日志】:路径总和、最大二叉树

59 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第13天,点击查看活动详情

1、写在前面

大家好,这里是【LeetCode刷题日志】。今天的两道题分别是:

  • 路径总和
  • 最大二叉树

2、内容

2.1、题目一

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

(1) 描述

image.png

(2) 举例

image.png

image.png

image.png

(3) 解题

递归法

/**
 * 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:
    // 自定义递归函数,前序遍历(中 左 右)
    bool traversal(TreeNode* cur, int sum) {
        // 1. 中
        if (!cur->left && !cur->right && sum == 0) {
            // 如果遇到叶子节点,并且目标总和已经减为 0,则返回 true
            return true;
        }
        if (!cur->left && !cur->right) {
            // 遇到叶子节点则返回 false
            return false;
        }
        // 2. 左
        if (cur->left != NULL) {
            sum -= cur->left->val; // 递归,处理节点;
            if (traversal(cur->left, sum)) return true;
            sum += cur->left->val; // 回溯,撤销处理结果
        }
        // 3. 右
        if (cur->right != NULL) {
            sum -= cur->right->val; // 递归,处理节点;
            if (traversal(cur->right, sum)) return true;
            sum += cur->right->val; // 回溯,撤销处理结果
        }
        return false;
    }
    // 主函数
    bool hasPathSum(TreeNode* root, int targetSum) {
        if (root == NULL) {
            return false;
        }
        return traversal(root, targetSum - root->val);
    }
};

迭代

class Solution {
public:
    bool hasPathSum(TreeNode* root, int targetSum) {
        if (root == NULL) return false;     // 如果是空节点,则返回 false
        stack<pair<TreeNode*, int>> st;     // 栈中存储元素为:pair<节点指针,路径数值>
        st.push(pair<TreeNode*, int>(root, root->val));  // 存储根节点信息 pair<root, root->val>
        // 当栈为空时退出循环
        while (!st.empty()) {
            // 1. 中:取到栈顶元素 node
            pair<TreeNode*, int> node = st.top(); st.pop();
            // 判断:是否有路径总和(如果 node 是叶子节点,并且从根结点到node的路径之和正好等于sum,则返回 true)
            if (!node.first->left && !node.first->right && targetSum == node.second) return true;
            // 2. 向右遍历
            TreeNode* rightNode = node.first->right;    // 右结点
            if (rightNode != NULL) {
                // 压入右边不为空的节点,并记录从根结点到该结点的路径数值之和
                st.push(pair<TreeNode*, int>(rightNode, node.second + rightNode->val));
            }
            // 3. 向左遍历
            TreeNode* leftNode = node.first->left;      // 左结点
            if (leftNode != NULL) {
                // 压入右边不为空的节点,并记录从根结点到该结点的路径数值之和
                st.push(pair<TreeNode*, int>(leftNode, node.second + leftNode->val));
            }
        }
        return false;
    }
};

2.2、题目二

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

(1) 描述

image.png

(2) 举例

image.png

image.png

(3) 解题

参考代码:

/**
 * 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:
    TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
        // 构建新节点
        TreeNode* node = new TreeNode(0);
        // 如果传入的数组只剩一个元素,则代表构造到叶子节点了
        if (nums.size() == 1) {
            // 返回该节点
            node->val = nums[0];
            return node;
        }
        int max = 0;           // 表示数组nums中的最大值
        int index = 0;         // 最大值所对应的下标
        // 遍历数组 nums
        for (int i = 0; i < nums.size(); i++) {
            if (nums[i] > max) {
                max = nums[i];
                index = i;
            }
        }
        // 将新构造的节点的值设置为当前数组的最大值
        node->val = max;
        // 向左遍历,构造左子树
        if (index > 0) {
            // 数组nums中最大值max的左区间为:[nums.begin(), nums.begin() + index]
            vector<int> vec(nums.begin(), nums.begin() + index);
            // 设置当前节点的左孩子
            node->left = constructMaximumBinaryTree(vec);
        }
        // 向右遍历,构造右子树
        if (index < (nums.size() - 1)) {
            // 数组nums中最大值max的右区间为:[nums.begin() + index + 1, nums.end()]
            vector<int> vec(nums.begin() + index + 1, nums.end());
            // 设置当前节点的右孩子
            node->right = constructMaximumBinaryTree(vec);
        }
        // 返回结点
        return node;
    }
};

3、写在最后

好的,今天就先刷到这里。