程式碼隨想錄演算法訓練營day18 | leetcode 513. 找樹左下角的值、112(113). 路徑總和(I、II)、105(106). 構造二叉樹

Humphreyr發表於2024-03-10

目錄
  • 題目連結:513. 找樹左下角的值-中等
  • 題目連結:112. 路徑總和-簡單
  • 題目連結:113. 路徑總和 II-中等
  • 題目連結:105. 從前序與中序遍歷序列構造二叉樹-中等
  • 題目連結:106. 從中序與後序遍歷序列構造二叉樹-中等

題目連結:513. 找樹左下角的值-中等

題目描述:

給定一個二叉樹的 根節點 root,請找出該二叉樹的 最底層 最左邊 節點的值。

假設二叉樹中至少有一個節點。

示例 1:

img

輸入: root = [2,1,3]
輸出: 1

示例 2:

img

輸入: [1,2,3,4,null,5,6,null,null,7]
輸出: 7

提示:

  • 二叉樹的節點個數的範圍是 [1,10^4]
  • -2^31 <= Node.val <= 2^31 - 1

迭代法:模板題

更新每層第一個數即可

程式碼如下:

/**
 * 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:
    int findBottomLeftValue(TreeNode* root) {
        queue<TreeNode*> que;
        int res;
        que.push(root);
        while(!que.empty()){
            int size = que.size();
            TreeNode* cur;
            for(int i = 0; i < size; ++i){
                cur = que.front();
                que.pop();
                if(i == 0) res = cur->val;
                if(cur->left) que.push(cur->left);
                if(cur->right) que.push(cur->right);
            }
        }
        return res;
    }
};

遞迴法:重點

程式碼如下:

class Solution {
public:
    int maxDepth = INT_MIN;
    int res;
    void traversal(TreeNode* root, int depth){
        if(root->left == NULL && root->right == NULL){
            if(depth > maxDepth){
                maxDepth = depth;
                res = root->val;
            }
            return;
        }
        // 一定要左在右前邊,這樣maxDepth一定是每次到達每一層最左側的時候更新的
        if(root->left){
            traversal(root->left, depth + 1);
        }
        if(root->right){
            traversal(root->right, depth + 1);
        }
    }
    int findBottomLeftValue(TreeNode* root) {
        traversal(root, 0);
        return res;
    }
};

題目連結:112. 路徑總和-簡單

題目描述:

給你二叉樹的根節點 root 和一個表示目標和的整數 targetSum 。判斷該樹中是否存在 根節點到葉子節點 的路徑,這條路徑上所有節點值相加等於目標和 targetSum 。如果存在,返回 true ;否則,返回 false

葉子節點 是指沒有子節點的節點。

示例 1:

img

輸入:root = [5,4,8,11,null,13,4,7,2,null,null,null,1], targetSum = 22
輸出:true
解釋:等於目標和的根節點到葉節點路徑如上圖所示。

示例 2:

img

輸入:root = [1,2,3], targetSum = 5
輸出:false
解釋:樹中存在兩條根節點到葉子節點的路徑:
(1 --> 2): 和為 3
(1 --> 3): 和為 4
不存在 sum = 5 的根節點到葉子節點的路徑。

示例 3:

輸入:root = [], targetSum = 0
輸出:false
解釋:由於樹是空的,所以不存在根節點到葉子節點的路徑。

提示:

  • 樹中節點的數目在範圍 [0, 5000]
  • -1000 <= Node.val <= 1000
  • -1000 <= targetSum <= 1000

迭代法:模板題-簡單

程式碼如下:

/**
 * 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 hasPathSum(TreeNode* root, int targetSum) {
        if (root == NULL)
            return false;
        if (root->val == targetSum && !root->left && !root->right)
            return true;
        queue<TreeNode*> queTree;
        queue<int> subSum;
        queTree.push(root);
        subSum.push(root->val);
        while (!queTree.empty()) {
            TreeNode* cur = queTree.front();
            queTree.pop();
            int sum = subSum.front();
            subSum.pop();
            if (cur->left) {
                if (targetSum - cur->left->val == sum && !cur->left->left && !cur->left->right)
                    return true;
                queTree.push(cur->left);
                subSum.push(sum + cur->left->val);
            }
            if (cur->right) {
                if (targetSum - cur->right->val == sum && !cur->right->left && !cur->right->right)
                    return true;
                queTree.push(cur->right);
                subSum.push(sum + cur->right->val);
            }
        }
        return false;
    }
};

遞迴法:

程式碼如下:

class Solution {
public:
    bool hasPathSum(TreeNode* root, int targetSum) {
        if (root == NULL)
            return false;
        if (!root->left && !root->right && targetSum == root->val)
            return true;
        bool leftSum = hasPathSum(root->left, targetSum - root->val);
        bool rightSum = hasPathSum(root->right, targetSum - root->val);
        return leftSum || rightSum;
    }
};

題目連結:113. 路徑總和 II-中等

題目描述:

給你二叉樹的根節點 root 和一個整數目標和 targetSum ,找出所有 從根節點到葉子節點 路徑總和等於給定目標和的路徑。

葉子節點 是指沒有子節點的節點。

示例 1:

img

輸入:root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22
輸出:[[5,4,11,2],[5,8,4,5]]

示例 2:

img

輸入:root = [1,2,3], targetSum = 5
輸出:[]

示例 3:

輸入:root = [1,2], targetSum = 0
輸出:[]

提示:

  • 樹中節點總數在範圍 [0, 5000]
  • -1000 <= Node.val <= 1000
  • -1000 <= targetSum <= 1000

程式碼如下:

class Solution {
public:
    vector<vector<int>> res;
    vector<int> subPath;
    void traversal(TreeNode* root, int targetSum){
        if(root == NULL) return;
        subPath.push_back(root->val);
        if(!root->left && !root->right && targetSum == root->val){
            res.push_back(subPath);
        }
        if(root->left)
            traversal(root->left, targetSum - root->val);
        if(root->right)
            traversal(root->right, targetSum - root->val);
        subPath.pop_back();
        return;
    }
    vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
        traversal(root, targetSum);
        return res;
    }
};

題目連結:105. 從前序與中序遍歷序列構造二叉樹-中等

題目描述:

給定兩個整數陣列 preorderinorder ,其中 preorder 是二叉樹的先序遍歷inorder 是同一棵樹的中序遍歷,請構造二叉樹並返回其根節點。

示例 1:

img

輸入: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
輸出: [3,9,20,null,null,15,7]

示例 2:

輸入: preorder = [-1], inorder = [-1]
輸出: [-1]

提示:

  • 1 <= preorder.length <= 3000
  • inorder.length == preorder.length
  • -3000 <= preorder[i], inorder[i] <= 3000
  • preorderinorder無重複 元素
  • inorder 均出現在 preorder
  • preorder 保證 為二叉樹的前序遍歷序列
  • inorder 保證 為二叉樹的中序遍歷序列

程式碼如下:

/**
 * 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* buildTree(vector<int>& preorder, vector<int>& inorder) {
        if (preorder.size() == 0)
            return NULL;
        // 第一個元素即為當前中間節點
        int rootVal = preorder[0];
        TreeNode* root = new TreeNode(rootVal);

        // 葉子節點
        if (preorder.size() == 1)
            return root;

        // 找切割點
        int rootIndex =
            find(inorder.begin(), inorder.end(), rootVal) - inorder.begin();

        // 切割中序陣列得到中序左陣列和中序右陣列
        vector<int> leftIn(inorder.begin(), inorder.begin() + rootIndex);
        vector<int> rightIn(inorder.begin() + rootIndex + 1, inorder.end());
        // 刪掉第一個元素
        preorder.erase(preorder.begin());
        // 切割前序陣列,得到前序左陣列和前序右陣列
        vector<int> leftPre(preorder.begin(), preorder.begin() + leftIn.size());
        vector<int> rightPre(preorder.end() - rightIn.size(), preorder.end());

        root->left = buildTree(leftPre, leftIn);
        root->right = buildTree(rightPre, rightIn);

        return root;
    }
};

題目連結:106. 從中序與後序遍歷序列構造二叉樹-中等

題目描述:

給定兩個整數陣列 inorderpostorder ,其中 inorder 是二叉樹的中序遍歷, postorder 是同一棵樹的後序遍歷,請你構造並返回這顆 二叉樹

示例 1:

img

輸入:inorder = [9,3,15,20,7], postorder = [9,15,7,20,3]
輸出:[3,9,20,null,null,15,7]

示例 2:

輸入:inorder = [-1], postorder = [-1]
輸出:[-1]

提示:

  • 1 <= inorder.length <= 3000
  • postorder.length == inorder.length
  • -3000 <= inorder[i], postorder[i] <= 3000
  • inorderpostorder 都由 不同 的值組成
  • postorder 中每一個值都在 inorder
  • inorder 保證是樹的中序遍歷
  • postorder 保證是樹的後序遍歷

程式碼如下:

/**
 * 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* buildTree(vector<int>& inorder, vector<int>& postorder) {
        if (postorder.size() == 0)
            return NULL;
        // 第一個元素即為當前中間節點
        int rootVal = postorder[postorder.size() - 1];
        TreeNode* root = new TreeNode(rootVal);

        // 葉子節點
        if (postorder.size() == 1)
            return root;

        // 找切割點
        int rootIndex =
            find(inorder.begin(), inorder.end(), rootVal) - inorder.begin();

        // 切割中序陣列得到中序左陣列和中序右陣列
        vector<int> leftIn(inorder.begin(), inorder.begin() + rootIndex);
        vector<int> rightIn(inorder.begin() + rootIndex + 1, inorder.end());
        // 刪掉第一個元素
        // postorder.resize(postorder.size() - 1);
        postorder.erase(postorder.end() - 1);
        // 切割後序陣列,得到後序左陣列和後序右陣列
        vector<int> leftPost(postorder.begin(), postorder.begin() + leftIn.size());
        vector<int> rightPost(postorder.end() - rightIn.size(), postorder.end());

        root->left = buildTree(leftIn, leftPost);
        root->right = buildTree(rightIn, rightPost);

        return root;
    }
};

相關文章