LeetCode 第十八天

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

cpp 复制代码
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<TreeNode*> que;
        // if(root)
        //     que.push(root);
        // while(!que.empty())
        // {
        //     int size = que.size();
        //     bool flag = false;
        //     vector<int> vec;
        //     for(int i = 0; i<size; 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. 路径总和

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

cpp 复制代码
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数组,通过引用方式传递,存储结果。精华在代码处和注释。

cpp 复制代码
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. 从中序与后序遍历序列构造二叉树

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

cpp 复制代码
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. 从前序与中序遍历序列构造二叉树

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

cpp 复制代码
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);
    }
};
相关推荐
CSDN_Colinw1 分钟前
C++模块化设计原则
开发语言·c++·算法
MicroTech20253 分钟前
微算法科技(NASDAQ: MLGO)使用机器学习保障量子安全下区块链高效可用
科技·算法·机器学习
m0_662577974 分钟前
C++中的模板方法模式
开发语言·c++·算法
参.商.4 分钟前
【Day47】912. 排序数组【6 种排序】
leetcode·golang·排序算法
We་ct6 分钟前
LeetCode 33. 搜索旋转排序数组:O(log n)二分查找
前端·算法·leetcode·typescript·个人开发·二分·数组
智驱力人工智能7 分钟前
一盔一带AI抓拍系统能否破解非机动车执法取证难 骑行未戴头盔检测 电动车未戴头盔智能监测 摩托车头盔佩戴AI识别系统 边缘计算实时处理
人工智能·算法·yolo·目标检测·边缘计算
重生之我是Java开发战士10 分钟前
【优选算法】优先级队列:最后一块石头的重量,数据流中的第K大元素,前K个高频单词,数据流中的中位数
数据结构·算法·leetcode
智算菩萨13 分钟前
音频处理基础理论:从物理声波到数字信号完整知识体系
算法·机器学习·电脑·音视频
小高求学之路1 小时前
计算机视觉、YOLO算法模型训练、无人机监测人员密集自动识别
算法·yolo·计算机视觉
散峰而望1 小时前
【基础算法】剪枝与记忆化搜索:算法优化的双刃剑,效率倍增的实战指南
算法·机器学习·剪枝