代码随想录刷题第18天

第一题是找树左下角的值https://leetcode.cn/problems/find-bottom-left-tree-value/description/,没啥思路。看看题解代码随想录。卡哥提到了层序遍历,上手写一下,一遍整出。

class Solution {
public:
    int findBottomLeftValue(TreeNode* root) {
        queue que;
        int result = 0;
        if (root != NULL)
            que.push(root);
        while (!que.empty()) {
            int size = que.size();
            for (int i = 0; i < size; i++) {
                TreeNode* node = que.front();
                que.pop();
                if (i == 0)
                    result = node->val;//记录每一行的最左端元素,最后一行覆盖结果
                if (node->left)
                    que.push(node->left);
                if (node->right)
                    que.push(node->right);
            }
        }
        return result;
    }
};

递归方法通过更新叶子结点的深度值,先遍历左,后遍历右,保证找到的第一个深度最大的叶子结点是最后一行最左侧的点。

class Solution {
public:
    int maxdepth = INT_MIN;
    int result;
    void travel(TreeNode* node, int depth) { //确定递归函数的参数和返回值
        if (node->left == NULL && node->right == NULL) { //确定终止条件
            if (maxdepth < depth) {
                maxdepth = depth;
                result = node->val;
            }
            return;
        }
        if (node->left) { //确定单层递归逻辑
            depth++;
            travel(node->left, depth);
            depth--; //回溯,返回上层
        }
        if (node->right) {
            depth++;
            travel(node->right, depth);
            depth--;
        }
        return;
    }

    int findBottomLeftValue(TreeNode* root) {
        travel(root, 0);
        return result;
    }
};

拿下。

第二题是路径总和https://leetcode.cn/problems/path-sum/description/,有点想法了,写了一遍发现细节还是不清楚,如何由下向上返回判断结果。看题解才写出来第一遍代码。

class Solution {
public:
    bool travel(TreeNode* node, int count) { //确定递归函数的参数与返回类型//
        if (node->left == NULL && node->right == NULL && count == 0)
            return true;
        if (node->left == NULL && node->right == NULL && count != 0)
            return false; //终止递归逻辑//
        if (node->left) {
            count -= node->left->val;
            if (travel(node->left, count))
                return true; //向上返回true//
            count += node->left->val;
        }
        if (node->right) {
            count -= node->right->val;
            if (travel(node->right, count))
                return true;
            count += node->right->val; //回溯//
        }
        return false;
    }
    bool hasPathSum(TreeNode* root, int targetSum) {
        if (root == NULL)
            return false;
        return travel(root, targetSum - root->val);
    }
};

迭代用栈也是可以的。

class Solution {
public:
    bool hasPathSum(TreeNode* root, int targetSum) {
        if (root == NULL)
            return false;
        stack> st;
        st.push(pair(root, root->val));
        while (!st.empty()) {
            pair node = st.top();
            st.pop();
            if (!node.first->left && !node.first->right &&
                targetSum == node.second)
                return true;
            if (node.first->right)
                st.push(pair(
                    node.first->right, node.second + node.first->right->val));
            if (node.first->left)
                st.push(pair(
                    node.first->left, node.second + node.first->left->val));
        }
        return false;
    }
};

相似题目是https://leetcode.cn/problems/path-sum-ii/,不过此题需要我们遍历整颗树,因此递归函数不需要返回值。

class Solution {
public:
    vector> result;
    vector path;
    void travel(TreeNode* node, int count) {
        if (!node->left && !node->right && count == 0) {
            result.push_back(path);
            return;
        }
        if (!node->left && !node->right)
            return;
        if (node->left) {
            path.push_back(node->left->val);
            count -= node->left->val;
            travel(node->left, count);
            count += node->left->val;
            path.pop_back();
        }
        if (node->right) {
            path.push_back(node->right->val);
            count -= node->right->val;
            travel(node->right, count);
            count += node->right->val;
            path.pop_back();
        }
        return;
    }
    vector> pathSum(TreeNode* root, int targetSum) {
        result.clear();
        path.clear();
        if (root == NULL)
            return result;
        path.push_back(root->val);
        travel(root, targetSum - root->val);
        return result;
    }
};

第三题是构造二叉树力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台,直接上卡哥讲解。重点在于切割两个数组,再对切割结果进行递归。

class Solution {
public:
    TreeNode* travel(vector& inorder, vector& postorder) {
        if (postorder.size() == 0)
            return NULL;
        int rootValue =
            postorder[postorder.size() - 1]; //后序最后一个为根节点//
        TreeNode* root = new TreeNode(rootValue);
        if (postorder.size() == 1)
            return root;
        int delimiterIndex;
        for (delimiterIndex = 0; delimiterIndex < inorder.size();
             delimiterIndex++) { //找切割点//
            if (inorder[delimiterIndex] == rootValue)
                break;
        }
        vector leftInorder(inorder.begin(),
                                inorder.begin() +
                                    delimiterIndex); //确定中序左子树//
        vector rightInorder(inorder.begin() + delimiterIndex + 1,
                                 inorder.end()); //确定中序右子树//
        postorder.resize(postorder.size() - 1);  //丢最后一个数组//
        vector leftPostorder(postorder.begin(),
                                  postorder.begin() +
                                      leftInorder.size()); //确定后序左子树//
        vector rightPostorder(postorder.begin() + leftInorder.size(),
                                   postorder.end()); //确定后序右子树//
        root->left = travel(leftInorder, leftPostorder);
        root->right = travel(rightInorder, rightPostorder);
        return root;
    }
    TreeNode* buildTree(vector& inorder, vector& postorder) {
        if (inorder.size() == 0 || postorder.size() == 0)
            return NULL;
        return travel(inorder, postorder);
    }
};

下标法规避了建立vector的麻烦。

class Solution {
public:
    TreeNode* travel(vector& inorder, int inorderBegin, int inorderEnd, vector& postorder, int postorderBegin, int postorderEnd){
        if (postorderBegin == postorderEnd) return NULL;
        int rootValue = postorder[postorderEnd - 1];
        TreeNode* root = new TreeNode(rootValue);
        if (postorderBegin - postorderEnd == 1) return root;
        int delimiterIndex;
        for(delimiterIndex = 0; delimiterIndex < inorderEnd; delimiterIndex++){
            if (inorder[delimiterIndex] == rootValue) break;
        }
        //切割中序数组
        int leftInorderBegin = inorderBegin;
        int leftInorderEnd = delimiterIndex;
        int rightInorderBegin = delimiterIndex + 1;
        int rightInorderEnd = inorderEnd;
        //切割后序数组
        int leftPostorderBegin = postorderBegin;
        int leftPostorderEnd = postorderBegin + delimiterIndex - inorderBegin;
        int rightPostordreBegin = postorderBegin + delimiterIndex - inorderBegin;
        int rightPostordreEnd = postorderEnd - 1;
        root->left = travel(inorder, leftInorderBegin, leftInorderEnd, postorder, leftPostorderBegin, leftPostorderEnd);
        root->right = travel(inorder,rightInorderBegin, rightInorderEnd, postorder, rightPostordreBegin, rightPostordreEnd);
        return root;

    }
    TreeNode* buildTree(vector& inorder, vector& postorder) {
    if (inorder.size() == 0 || postorder.size() == 0) return NULL;
    return travel(inorder, 0, inorder.size(), postorder, 0, postorder.size());
    }
};

下一题是用前序和中序构造二叉树,照猫画虎 。

class Solution {
public:
    TreeNode* travel(vector& preorder, vector& inorder){
    if (preorder.size() == 0) return NULL;
    int rootvalue = preorder[0];//中间节点//
    TreeNode* root = new TreeNode(rootvalue);
    if (preorder.size() == 1) return root;//叶子结点返回根//
    int delimiterIndex;
    for(delimiterIndex = 0; delimiterIndex < inorder.size(); delimiterIndex++){
        if (inorder[delimiterIndex] == rootvalue) break;//找到切割点//
    }
//切中序数组
    vector leftInorder(inorder.begin(), inorder.begin() + delimiterIndex);
    vector  rightInorder(inorder.begin() + delimiterIndex + 1, inorder.end());
//切前序数组   
    vector leftPreorder(preorder.begin() + 1, preorder.begin() + leftInorder.size());
    vector rightPreorder(preorder.begin() + leftInorder.size(), preorder.end());
    root->left = travel(leftPreorder, leftInorder);
    root->right = travel(rightPreorder, rightInorder);
    return root;
    }
    TreeNode* buildTree(vector& preorder, vector& inorder) {
    if (preorder.size() == 0 || inorder.size() == 0) return NULL;
    return travel(preorder, inorder);
    }
};

下标法如下:

class Solution {
public:
    TreeNode* travel(vector& preorder, int preorderBegin, int preorderEnd, vector& inorder, int inorderBegin, int inorderEnd){
        if (preorderBegin == preorderEnd) return NULL;
        int rootValue = preorder[preorderBegin];
        TreeNode* root = new TreeNode(rootValue);
        if (preorderEnd - preorderBegin == 1) return root;
        //找中序切割点
        int delimiterIndex;
        for (delimiterIndex = 0; delimiterIndex < inorderEnd; delimiterIndex++){
            if (inorder[delimiterIndex] == rootValue) break;
        }
        //切割中序
        int leftinorderBegin = inorderBegin;
        int leftinorderEnd = delimiterIndex;
        int rightinorderBegin = delimiterIndex + 1;
        int rightinorderEnd = inorderEnd;
        //切割后序
        int leftpreorderBegin = preorderBegin + 1;
        int leftpreorderEnd = preorderBegin + 1 + delimiterIndex - inorderBegin;
        int rightpreorderBegin = preorderBegin + 1 + delimiterIndex - inorderBegin;
        int rightpreorderEnd = preorderEnd;
        root->left = travel(preorder, leftpreorderBegin, leftpreorderEnd, inorder, leftinorderBegin, leftinorderEnd);
        root->right = travel(preorder, rightpreorderBegin, rightpreorderEnd, inorder, rightinorderBegin, rightinorderEnd);
        return root;

    }
    TreeNode* buildTree(vector& preorder, vector& inorder) {
    if (preorder.size() == 0 || inorder.size() == 0) return NULL;
    return travel(preorder, 0, preorder.size(), inorder, 0, inorder.size());
    }
};

今天的最大收获是用中序和后序,中序和前序建立二叉树。再一次加深了对递归和回溯的掌握。

你可能感兴趣的:(leetcode,算法,职场和发展)