代码随想录算法训练营第21天 | 513.找树左下角的值、112. 路径总和、113.路径总和ii、106.从中序与后序遍历序列构造二叉树、105.从前序与中序遍历序列构造二叉树

2024/5/1 代码随想录算法训练营第21天 | 513.找树左下角的值、112. 路径总和、113.路径总和ii、106.从中序与后序遍历序列构造二叉树、105.从前序与中序遍历序列构造二叉树

513.找树左下角的值

题目链接 513
给定一个二叉树的 根节点 root,请找出该二叉树的 最底层 最左边 节点的值。

假设二叉树中至少有一个节点。
随想录

第一次提交

直接想到层序遍历,轻松AC

class Solution {
public:
    int findBottomLeftValue(TreeNode* root) {
        if (!root) return -1;
        int res = root -> val; 
        queue<TreeNode*> que;
        que.push(root);
        while(!que.empty()) {
            res = que.front()->val;
            int size = que.size();
            for (int i = 0; i < size; i++) {
                TreeNode* cur = que.front();
                que.pop();
                if (cur->left) que.push(cur->left);
                if (cur->right) que.push(cur->right);
            }
        }
        return res;       
    }
};

学习题解

递归方法
深度遍历
视频链接

class Solution {
public:
    int maxDepth = 0;
    int res = -1;
    void traversal (TreeNode* node, int depth) {
        if (node->left == nullptr && node->right == nullptr && depth > maxDepth) {
            maxDepth = depth;
            res = node->val;
        }
        if (node->left) traversal(node->left, depth + 1);//这里隐藏了对depth 的回溯
        if (node->right) traversal(node->right, depth + 1);
    }
    int findBottomLeftValue(TreeNode* root) {
        res = root->val;
        traversal(root, 0);
        return res;           
    }
};

112. 路径总和

题目链接 112

第一次提交

简单迭代

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

学习优秀题解

视频链接
深度遍历回溯方法

多一种终止条件

class Solution {
public:
    bool hasPathSum(TreeNode* root, int targetSum) {
        if (!root) return false;
        if (root->left == nullptr && root->right == nullptr && targetSum == root->val) return true;
        //这种情况下也可以剪枝
        if (root->left == nullptr && root->right == nullptr && targetSum != root->val) return false;
        return hasPathSum(root->left, targetSum - root->val) || hasPathSum(root->right, targetSum - root->val);
    }
};

113.路径总和ii

题目链接 给你二叉树的根节点 root 和一个整数目标和 targetSum ,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。
叶子节点 是指没有子节点的节点。

很自然的想到回溯

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

随想录
整体思路变化不大

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

题目链接 106 给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。

第一次提交

直接找规律递归

注意边界条件和特殊情况的判定,[]; [1]

class Solution {
public:
    int findNode (vector<int>& inorder, int target) {
        for (int i = 0 ; i < inorder.size(); i++) {
            if (target == inorder[i]) return i;
        }
        return -1;
    }
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        if (inorder.size() == 0) return nullptr;
        TreeNode* root = new TreeNode();
        root->val = postorder[postorder.size() - 1];
        if (inorder.size() == 1) return root;
        int leftTreeLength = findNode(inorder, root->val);//1
        int rightTreeLength =  postorder.size() - leftTreeLength - 1;//3
        vector<int> leftInorder = vector<int> (inorder.begin(),inorder.begin() + leftTreeLength);//[0,1)
        vector<int> leftPostorder = vector<int> (postorder.begin(),postorder.begin() + leftTreeLength);//[0, 1)
        vector<int> rightInorder = vector<int> (inorder.begin() + leftTreeLength + 1, inorder.end());//[2,6)
        vector<int> rightPostorder = vector<int> (postorder.begin() + leftTreeLength, postorder.begin() + leftTreeLength + rightTreeLength);//[1, 5)
        root->left = buildTree(leftInorder,leftPostorder );
        root->right = buildTree(rightInorder, rightPostorder);
        return root;
    }
};

学习优秀题解

随想录:建立索引而不是创建新的vector

这里的经验是创造左闭右开的集合比较好进行计算,用一个例子去验证编号是否正确。

class Solution {
public:
    int findNode(vector<int> vec, int start, int end, int target) {
        for (int i = start; i < end; i++) {
            if (target == vec[i]) return i;
        }
        return -1;
    }
    TreeNode* traversal(vector<int>& inorder, vector<int>& postorder, int inorderStart, int InorderEnd, int postorderStart, int postorderEnd) {
        if (inorderStart == InorderEnd) return nullptr;
        TreeNode* node = new TreeNode(postorder[postorderEnd - 1]);
        if (inorderStart +1 == InorderEnd) return node;
        int leftTreeEnd = findNode(inorder, inorderStart, InorderEnd, node->val);
        node->left = traversal(inorder, postorder, inorderStart, leftTreeEnd, postorderStart, postorderStart +leftTreeEnd - inorderStart);
        node->right = traversal(inorder, postorder, leftTreeEnd + 1, InorderEnd,  postorderStart +leftTreeEnd - inorderStart, postorderEnd - 1);
        return node;
         
    }
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        return traversal(inorder,postorder,0, inorder.size(), 0, postorder.size());
    }
};

105.从前序与中序遍历序列构造二叉树

题目链接 105

递归方法

这里直接写一遍用索引的迭代方式

class Solution {
public:
    int findNode(vector<int>& vec, int start, int end, int target) {
        for (int i = start; i < end; i++) {
            if (vec[i] == target) return i;
        }
        return -1;
    }
    TreeNode* traversal(vector<int>& preorder, vector<int>& inorder, int preStart, int preEnd, int inStart, int inEnd) {
        if (preStart == preEnd) return nullptr;
        TreeNode* node = new TreeNode(preorder[preStart]);//1
        if (preEnd == 1 + preStart) return node;
        int inorderLeftEnd = findNode(inorder, inStart, inEnd, node->val);//2
        cout<< inorderLeftEnd <<endl;
        cout<< preStart+1 <<" <<"<< 1+inorderLeftEnd <<" <<"<< inStart <<" <<"<<inorderLeftEnd<<endl;
        node->left = traversal(preorder, inorder, preStart+1 , preStart + 1 + inorderLeftEnd - inStart, inStart, inorderLeftEnd);
        //[1,3); [0, 2)
        node->right = traversal(preorder, inorder,  preStart + 1 + inorderLeftEnd - inStart, preEnd, inorderLeftEnd+ 1, inEnd);
        //[3,3); [3,3) RETURN NULLPTR
        return node;
    }
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        return traversal(preorder, inorder, 0, preorder.size(), 0, inorder.size());
    }
};

迭代方法

class Solution {
public:
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        if (preorder.size() == 0) return nullptr;
        TreeNode* root = new TreeNode(preorder[0]);
        stack<TreeNode*> stk;
        stk.push(root);
        int index = 0;
        for (int i = 1 ; i< preorder.size(); i++) {
            TreeNode* nextNode = new TreeNode(preorder[i]);
            TreeNode* curr = stk.top();
            if(curr-> val != inorder[index]) {
                stk.push(nextNode);
                curr-> left = nextNode;
            } else {
                while (!stk.empty() && stk.top()-> val == inorder[index]) {
                    curr = stk.top();
                    index ++;
                    stk.pop();
                }
                stk.push(nextNode);
                curr -> right = nextNode;
            }
        }
        return root;
    }
};
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值