LeetCode 第十八天

513. 找树左下角的值
层序遍历秒杀,但是我还是学写优雅的递归

class Solution {
public:
	//注意这两个是全局变量
    int res;
    int maxDepth = INT_MIN;
    void getMostLeft(TreeNode* node, int depth)
    {
        // 如果为叶子节点,那么开始判断
        if(node->left == nullptr && node->right == nullptr)
        {
            if(depth > maxDepth)
            {
                maxDepth = depth;
                res = node->val;
            }
            return;
        }
        // 必须要对node->left加一个判断
        if(node->left)
        {
            depth++;
            getMostLeft(node->left, depth);
            depth--;
        }
        // 对node->right加一个判断
        if(node->right)
        {
            depth++;
            getMostLeft(node->right, depth);
            depth--;
        }
    }
    int findBottomLeftValue(TreeNode* root) {
        // 卡哥说的迭代模板题
        // queue que;
        // if(root)
        //     que.push(root);
        // while(!que.empty())
        // {
        //     int size = que.size();
        //     bool flag = false;
        //     vector vec;
        //     for(int i = 0; i
        //     {
        //         TreeNode* tmp = que.front();
        //         que.pop();
        //         vec.push_back(tmp->val);
        //         if(tmp->left)
        //         {
        //             que.push(tmp->left);
        //             flag = true;
        //         }
        //         if(tmp->right)
        //         {
        //             que.push(tmp->right);
        //             flag = true;
        //         }
        //     }
        //     if(!flag)
        //         return *vec.begin();

        // }
        // return 0;

        // 递归法
    if (root)
        getMostLeft(root,0);
    return res;
    }
};

112. 路径总和

同样是叶子结点的题目,对节点的左节点的右节点操作,不对节点本身操作,因此要注意根节点的单独处理。

class Solution {
public:
    bool traversal(TreeNode* root, vector<int>& vec, int targetSum)
    {
        // 叶子结点, 就判断
        if(root->left == nullptr && root->right == nullptr)
        {
            int sum = 0;
            for(int i = 0;i < vec.size(); i++)
            {
                sum += vec[i];
            }
            if(sum == targetSum)
            {
                return true;
            }
            return false;
        }
        // 左节点
        if(root->left)
        {
            vec.push_back(root->left->val);
            bool res = traversal(root->left, vec, targetSum);
            if(res)
                return true;
                // 回溯过程
            vec.pop_back();
        }
        // 右节点
        if(root->right)
        {
            vec.push_back(root->right->val);
            bool res = traversal(root->right, vec, targetSum);
            if(res)
                return true;
            vec.pop_back();
        }
        // 所有情况结束后要单独加一个返回
        return false;
    }
    bool hasPathSum(TreeNode* root, int targetSum) {
        vector<int> vec;
        bool res = false;
        if(root == nullptr)
            return false;
            //由于处理的是左右孩子节点,因此需要传入的目标值要减去根节点的值 
        return traversal(root, vec, targetSum - root->val);
    }
};

113. 路径总和 II

这题不过是加一个二维vector数组,通过引用方式传递,存储结果。精华在代码处和注释。

class Solution {
public:
    void getAllPath(TreeNode* root, vector<vector<int>>& res, vector<int>& vec, int targetSum)
    {
        // 叶子结点单独处理
        if(root->left == nullptr && root->right == nullptr)
        {
            int sum = 0;
            for(auto i : vec)
            {
                sum += i;
            }
            // 相加和等于目标值,存入结果集
            if(sum == targetSum)
            {
                res.push_back(vec);
            }
        }
        // 左节点不为空
        if(root->left)
        {
            vec.push_back(root->left->val);
            getAllPath(root->left, res, vec, targetSum);
            // 回溯
            vec.pop_back();
        }
        if(root->right)
        {
            vec.push_back(root->right->val);
            getAllPath(root->right, res, vec, targetSum);
            vec.pop_back();
        }
    }
    vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
        vector<vector<int>> res;
        vector<int> vec;
        if(root == nullptr)
            return res;
        else
        {
            // 因为这个不对本节点处理,是对左右孩子节点处理,因此需要先把根节点存入结果
            vec.push_back(root->val);
            getAllPath(root, res, vec, targetSum);
        }
        return res;
    }
};

总结:前三道题目都是对叶子结点的处理,那么就需要判断节点的左右孩子是否为空,为空则为叶子结点。同时在递归遍历之前需要对每个节点做是否为空判断。对于回溯,我一直理解递归代码都在尝试回溯,因此也不算难理解,以上代码写出了回溯的过程,即采用引用传递,节省每一层的空间;若是以前的方法则省略了回溯的过程,每一层的变量单独保存,造成空间的浪费。

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

重量级题目,曾经就在想这个题目的解法,但是都搁置了,现在刷到,非常滴珍贵。

class Solution {
public:
    TreeNode* traversal(vector<int>& inorder, vector<int>& postorder){
        // 空节点返回null
        if(postorder.size() == 0) return nullptr;
        int rootValue = postorder[postorder.size()-1];//后序遍历最后一个数
        // 新建的一个节点
        TreeNode* root = new TreeNode(rootValue);
        // 本句注释掉也可以
        if(postorder.size() == 1) return root;
        // 中序分割
        int index;
        for(index = 0; index < inorder.size(); index++)
        {
            if(inorder[index] == rootValue)
                break;
        }
        vector<int> leftInorder(inorder.begin(), inorder.begin() + index);
        vector<int> rightInorder(inorder.begin() + index + 1,inorder.end());
        // 后序分割
        postorder.resize(postorder.size() - 1);
        vector<int> leftPostorder(postorder.begin(),postorder.begin() + leftInorder.size());
        vector<int> rightPostorder(postorder.begin() + leftInorder.size(), postorder.end());
        // 接上子节点
        root->left = traversal(leftInorder, leftPostorder);
        root->right = traversal(rightInorder, rightPostorder);
        return root;
    }
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        // 空树
        if(inorder.size() == 0 || postorder.size() == 0) return nullptr;
        return traversal(inorder, postorder);
    }
};

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

这题和上一题差不多,是必掌握的题目。现在先按照笨方法写出来,二刷再看角标法(更省空间,时间)。

class Solution {
public:
    TreeNode* traversal(vector<int>& preorder, vector<int>& inorder)
    {
        if(preorder.size() == 0)
            return nullptr;
        int rootValue = preorder[0];
        TreeNode* root = new TreeNode(rootValue);

        // 确定中序分割点
        int index;
        for(index = 0; index < inorder.size(); index++)
        {
            if(inorder[index] == rootValue) break;
        }
        // 分割中序
        vector<int> leftInorder(inorder.begin(), inorder.begin() + index);
        vector<int> rightInorder(inorder.begin() + index + 1, inorder.end());

        // 分割前序
        preorder.erase(preorder.begin());
        vector<int> leftPreorder(preorder.begin(), preorder.begin() + leftInorder.size());
        vector<int> rightPreorder(preorder.begin() + leftInorder.size(), preorder.end());

        // 开始构建树
        root->left = traversal(leftPreorder, leftInorder);
        root->right = traversal(rightPreorder, rightInorder);
        return root;


    }
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        if(preorder.size() == 0 || inorder.size() == 0)
            return nullptr;
        return traversal(preorder, inorder);
    }
};

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