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

LeetCode 513 找树左下角的值

题目链接:513

递归

思路:找左下角值,即找深度最大叶子节点中最左边的值。因此,可采用中左右顺序遍历,当遍历到叶子节点时,比较深度是否大于记录的最大深度,若大于则记录新的值与新的最大深度。由于顺序为左右,因此在同一深度上,一定是左边的节点值先记录,这样右边的节点值深度一样就不会被记录了。
代码:

/**
 * 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 max_depth_;
    int bottom_left_val_;
    void find(TreeNode* cur, int depth) {
        ++depth;
        if (!cur->left && !cur->right) {
            if (depth > max_depth_) {
                bottom_left_val_ = cur->val;
                max_depth_ = depth;
            }
            return;
        }
        if (cur->left) find(cur->left, depth);
        if (cur->right) find(cur->right, depth);
    }

    int findBottomLeftValue(TreeNode* root) {
        find(root, 0);
        return bottom_left_val_;
    }
};

迭代

思路:只需用层序遍历,记录每层的第一个节点即可
代码:

/**
 * 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 result;

        if (root) que.push(root);
        while (!que.empty()) {
            int size = que.size();
            for (int i=0; i<size; ++i) {
                TreeNode* cur = que.front();
                que.pop();
                if (i==0) result = cur->val;
                if (cur->left) que.push(cur->left);
                if (cur->right) que.push(cur->right);
            }
        }
        return result;
    }
};

LeetCode 112 路径总和

题目链接:112

递归

思路:递归至叶子节点,判断和是否相等,若相等则返回true。在单层递归中,向左右子树递归,判断左右子树中是否存在符合要求的叶子节点。
代码:

/**
 * 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 recurse(TreeNode* cur, int sum, int targetSum) {
        sum += cur->val;
        if (!cur->left && !cur->right) {
            if (sum == targetSum) return true;
            return false;
        }

        if (cur->left && recurse(cur->left, sum, targetSum)) return true;
        if (cur->right && recurse(cur->right, sum, targetSum)) return true;
        return false;
    }

    bool hasPathSum(TreeNode* root, int targetSum) {
        if (!root) return false;
        return recurse(root, 0, targetSum);
    }
};

代码精简:

/**
 * 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) return false;
        if (!root->left && !root->right) {
            if (targetSum == root->val) return true;
            return false;
        }

        return hasPathSum(root->left, targetSum-root->val) || (root->right && hasPathSum(root->right, targetSum-root->val));
    }
};

迭代

思路:维护两个栈,一个存节点,一个存路径和,对于叶子节点判断和是否相等。
代码:

/**
 * 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) {
        stack<TreeNode*> node_stack;
        stack<int> sum_stack;

        if (root) {
            node_stack.push(root);
            sum_stack.push(root->val);
        }
        while(!node_stack.empty()) {
            TreeNode* cur = node_stack.top();
            int sum = sum_stack.top();
            node_stack.pop();
            sum_stack.pop();
            if (!cur->left && !cur->right && sum==targetSum) return true;
            if (cur->left) {
                node_stack.push(cur->left);
                sum_stack.push(sum+cur->left->val);
            }
            if (cur->right) {
                node_stack.push(cur->right);
                sum_stack.push(sum+cur->right->val);
            }
        }
        return false;
    }
};

LeetCode 113 路径总和ii

题目链接:113

递归

思路:与112类似,在单层递归中,向左右子树递归至叶子节点。由于需将所有符合要求的路径保存至结果中,所以不能通过返回值提前返回。注意路径的回溯。
代码:

/**
 * 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:
    void recurse(TreeNode* cur, int count, vector<int>& path, vector<vector<int>>& paths) {
        path.push_back(cur->val);
        if (!cur->left && !cur->right) {
            if (count == cur->val) paths.push_back(path);
            return;
        }
        if (cur->left) {
            recurse(cur->left, count-cur->val, path, paths);
            path.pop_back();
        }
        if (cur->right) {
            recurse(cur->right, count-cur->val, path, paths);
            path.pop_back();
        }
    }

    vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
        vector<vector<int>> result;
        vector<int> path;

        if (!root) return result;
        recurse(root, targetSum, path, result);
        return result;
    }
};

迭代

思路:维护两个栈,一个存节点和值的pair,一个存路径,对于叶子节点判断和是否相等。
代码:

/**
 * 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:
    vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
        stack<pair<TreeNode*, int>> node_stack;
        stack<vector<int>> path_stack;
        vector<vector<int>> result;

        int sum = 0;
        if (root) {
            node_stack.push(make_pair(root, root->val));
            vector<int> path;
            path.push_back(root->val);
            path_stack.push(path);
        };
        while(!node_stack.empty()) {
            auto cur = node_stack.top();
            node_stack.pop();
            auto cur_path = path_stack.top();
            path_stack.pop();
            if (!cur.first->left && !cur.first->right && cur.second==targetSum) result.push_back(cur_path);
            if (cur.first->right) {
                node_stack.push(make_pair(cur.first->right, cur.second+cur.first->right->val));
                cur_path.push_back(cur.first->right->val);
                path_stack.push(cur_path);
                cur_path.pop_back();
            }
            if (cur.first->left) {
                node_stack.push(make_pair(cur.first->left, cur.second+cur.first->left->val));
                cur_path.push_back(cur.first->left->val);
                path_stack.push(cur_path);
                cur_path.pop_back();
            }
        }
        return result;
    }
};

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

题目链接:106
思路:中序为左中右,后序为左右中,因此后序的最后一个元素即为根节点,通过该根节点去分割中序,得到左子树的中序和右子树的中序,通过左子树中序的size分割后序,得到左右子树的后序,然后分别递归进一步分割左右子树。
代码:

/**
 * 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 mid_val = postorder[postorder.size()-1];
        TreeNode* root = new TreeNode(mid_val);
        
        vector<int>::iterator it = inorder.begin();
        for (it; it!=inorder.end(); ++it) {
            if (*it == mid_val) break;
        }
        vector<int> left_inorder(inorder.begin(), it);
        vector<int> right_inorder(it+1, inorder.end());

        it = postorder.begin() + left_inorder.size();
        vector<int> left_postorder(postorder.begin(), it);
        vector<int> right_postorder(it, postorder.end()-1);

        root->left = buildTree(left_inorder, left_postorder);
        root->right = buildTree(right_inorder, right_postorder);
        return root;
    }
};

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

题目链接:105
思路:与106类似,通过前序分割中序,再反过来分割前序。由于递归中不断构造新数组影响效率,此处采用传入索引的方式。
代码:

/**
 * 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* recurse(vector<int>& preorder, int prebegin, int preend, vector<int>& inorder, int inbegin, int inend) {
        if ((preend - prebegin) == 0) return NULL;

        int mid_val = preorder[prebegin];
        TreeNode* root = new TreeNode(mid_val);

        int mid_index_in;
        for (int i=inbegin; i<inend; ++i) {
            if (mid_val == inorder[i]) mid_index_in = i;
        }
        int left_inbegin = inbegin;
        int left_inend = mid_index_in;
        int right_inbegin = mid_index_in+1;
        int right_inend = inend;

        int left_prebegin = prebegin+1;
        int left_preend = left_prebegin + (left_inend - left_inbegin);
        int right_prebegin = left_preend;
        int right_preend = preend;

        root->left = recurse(preorder, left_prebegin, left_preend, inorder, left_inbegin, left_inend);
        root->right = recurse(preorder, right_prebegin, right_preend, inorder, right_inbegin, right_inend);
        return root;
    }

    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        return recurse(preorder, 0, preorder.size(), inorder, 0, inorder.size());
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值