首页 > 编程语言 >代码随想录算法训练营第16天|LeetCode112路径总和LeetCode113路径总和iiLeetCode106.从中序与后序遍历序列构造二叉树LeetCode105从前序与中序遍历序列构造二叉树

代码随想录算法训练营第16天|LeetCode112路径总和LeetCode113路径总和iiLeetCode106.从中序与后序遍历序列构造二叉树LeetCode105从前序与中序遍历序列构造二叉树

时间:2024-07-18 15:29:12浏览次数:16  
标签:preorder 遍历 int 中序 二叉树 数组 序列 path inorder

代码随想录算法训练营

Day16 代码随想录算法训练营第 16 天 |LeetCode112路径总和 LeetCode113路径总和ii LeetCode106.从中序与后序遍历序列构造二叉树 LeetCode105.从前序与中序遍历序列构造二叉树


目录


前言

LeetCode112路径总和,LeetCode113路径总和ii

讲解文档

LeetCode106.从中序与后序遍历序列构造二叉树LeetCode105从前序与中序遍历序列构造二叉树

讲解文档


一、LeetCode112路径总和

1.题目链接

LeetCode112路径总和

2.思路

(1)和路径问题一样的思路,前序遍历
(2)递归实现
1)参数:节点指针,路径数组引用,targetsum,和指针
2)终止条件:叶节点终止,求和,与targetsum比较,如果相等,则总数+1
3)单层递增:
中:存放路径(第一句进行存放,因为叶节点就要存放)
左:递归调用,回溯
右:递归调用,回溯
为什么在递归调用之前先判断是否为空指针
如果先判断Node非空,不在递归调用之前先判断是否为空指针

			p(node->left, path, targetsum, ans);
            path.pop_back();
            p(node->right, path, targetsum, ans);
            path.pop_back();

这样如果node->left是空节点,不会加到路径里面,但是还会进行pop_back

3.题解

class Solution {
public:
    void p(TreeNode* node, vector<int>& path, int targetsum, int* ans) {
        path.push_back(node->val);
        if (node->left == NULL && node->right == NULL) {
            int n = path.size();
            int s = 0;
            for (int i = 0; i < n; i++) {
                s += path[i];
            }
            if (s == targetsum)
                (*ans) += 1;
            return;
        }
        if (node->left != NULL) {
            p(node->left, path, targetsum, ans);
            path.pop_back();
        }
        if (node->right != NULL) {
            p(node->right, path, targetsum, ans);
            path.pop_back();
        }
    }
    bool hasPathSum(TreeNode* root, int targetSum) {
        int ans = 0;
        vector<int> path;
        if(root==NULL) return 0;
        p(root, path, targetSum, &ans);
        if (ans > 0)
            return 1;
        else
            return 0;
    }
};

二、LeetCode113路径总和ii

1.题目链接

LeetCode113路径总和ii

2.思路

(1)在LeetCode112路径总和的思路上修改
(2)每次到叶子结点时,将路径存放进数组,如果路径之和为targetsum的,则加入二维数组

3.题解

class Solution {
public:
    void p(TreeNode* node, vector<int>& path, int targetsum,
           vector<vector<int>>& ans) {
        path.push_back(node->val);
        if (node->left == NULL && node->right == NULL) {
            int n = path.size();
            int s = 0;
            vector<int> res;
            for (int i = 0; i < n; i++) {
                s += path[i];
                res.push_back(path[i]);
            }
            if (s == targetsum)
                ans.push_back(res);
            return;
        }
        if (node->left != NULL) {
            p(node->left, path, targetsum, ans);
            path.pop_back();
        }
        if (node->right != NULL) {
            p(node->right, path, targetsum, ans);
            path.pop_back();
        }
    }
    vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
        vector<vector<int>> ans;
        vector<int> path;
        if (root == NULL)
            return ans;
        p(root, path, targetSum, ans);
        return ans;
    }
};

三、LeetCode106.从中序与后序遍历序列构造二叉树

1.题目链接

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

2.思路

(1)每次后序数组最后一个元素为子树根节点
以后序数组最后一个元素为切割点,先切割中序数组,再用中序数组切割后序数组
(2)步骤
1)边界条件:如果数组大小为0,说明是空节点
2)如果数组不为空,以后续数组最后一个元素为子树根节点,
再判断数组长度是否为1,如果数组长度为1,说明已经是二叉树的根节点,返回
3)求后序数组最后一个元素在中序数组中的位置
4)切割中序数组:得到中序左数组,中序右数组
5)切割后序数组:得到后序左数组,后序右数组,确保中序左数组与后序左数组长度一致
6)递归,求左子结点,右子节点

3.题解

class Solution {
public:
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        if (postorder.size() == 0 || inorder.size() == 0)
            return NULL;

        int value = postorder[postorder.size() - 1];
        TreeNode* root = new TreeNode(value);
        if (postorder.size() == 1)
            return root;
        int index;
        for (index = 0; index < inorder.size(); index++) {
            if (inorder[index] == value)
                break;
        }
        vector<int> inorder_left(inorder.begin(), inorder.begin() + index);
        vector<int> inorder_right(inorder.begin() + index + 1, inorder.end());
        postorder.pop_back();
        vector<int> postorder_left(postorder.begin(),
                                   postorder.begin() + index);
        vector<int> postorder_right(postorder.begin() + index, postorder.end());
        root->left = buildTree(inorder_left, postorder_left);
        root->right = buildTree(inorder_right, postorder_right);
        return root;
    }
};

四、LeetCode105从前序与中序遍历序列构造二叉树

1.题目链接

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

2.思路

1)每次前序数组最后一个元素为子树根节点
以前序数组最后一个元素为切割点,先切割中序数组,再用中序数组切割前序数组
(2)步骤
1)边界条件:如果数组大小为0,说明是空节点
2)如果数组不为空,以后续数组最后一个元素为子树根节点,
再判断数组长度是否为1,如果数组长度为1,说明已经是二叉树的根节点,返回
3)求前序数组最后一个元素在中序数组中的位置
4)切割中序数组:得到中序左数组,中序右数组
5)切割前序数组:得到前序左数组,前序右数组,确保中序左数组与前序左数组长度一致
6)递归,求左子结点,右子节点
注意:切割是与LeetCode106不同的,不制作新的数组,而是移动起点和终点的指针,实际上中序数组和前序数组实际上没改变
为什么:数组不能从前端弹出元素

3.题解

class Solution {
public:
    TreeNode* trace(vector<int>& preorder, int preorder_head, int preorder_end,
                    vector<int>& inorder, int inorder_head, int inorder_end) {
        if (preorder_end == preorder_head)
            return NULL;
        if (inorder_end == inorder_head)
            return NULL;
        int value = preorder[preorder_head];
        TreeNode* root = new TreeNode(value);
        if (preorder_end - preorder_head == 1)
            return root;
        int index;
        for (index = inorder_head; index < inorder_end; index++) {
            if (inorder[index] == value)
                break;
        }
        int inorder_left_head = inorder_head;
        int inorder_left_end = index;
        int inorder_right_head = index + 1;
        int inorder_right_end = inorder_end;
        int preorder_left_head = preorder_head + 1;
        int preorder_left_end = preorder_head + index - inorder_head + 1;
        int preorder_right_head = preorder_head + index - inorder_head + 1;
        int preorder_right_end = preorder_end;
        root->left = trace(preorder, preorder_left_head, preorder_left_end,
                           inorder, inorder_left_head, inorder_left_end);
        root->right = trace(preorder, preorder_right_head, preorder_right_end,
                            inorder, inorder_right_head, inorder_right_end);
        return root;
    }
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        if (preorder.size() == 0 || inorder.size() == 0)
            return NULL;
        return trace(preorder, 0, preorder.size(), inorder, 0, inorder.size());
    }
};

总结

1、路径之和:与昨天的路径问题思路相似,前序递归
每次遇到叶子结点时求路径之和并进行比较
2、数组构造二叉树
(1)前序数组的第一个元素为子树根节点,由于数组不可以从前端弹出元素,分割数组是通过指针移动实现的,不产生新的数组
(2)后续数组最后一个元素为子树根节点,分割数组产生新的数组

标签:preorder,遍历,int,中序,二叉树,数组,序列,path,inorder
From: https://blog.csdn.net/2301_79647020/article/details/140513477

相关文章

  • 代码随想录算法训练营第 15 天 |LeetCode110平衡二叉树 LeetCode257二叉树的所有路径
    代码随想录算法训练营Day15代码随想录算法训练营第15天|LeetCode110平衡二叉树LeetCode257二叉树的所有路径LeetCode404左叶子之和LeetCode222完全二叉树节点之和目录代码随想录算法训练营前言LeetCode110平衡二叉树LeetCode257二叉树的所有路径LeetCode404左......
  • 【web]-php反序列化-复杂1(转)
    转自:PHP反序列化-CSDN博客反序列化漏洞是基于序列化和反序列化的操作,在反序列化——unserialize()时存在用户可控参数,而反序列化会自动调用一些魔术方法,如果魔术方法内存在一些敏感操作例如eval()函数,而且参数是通过反序列化产生的,那么用户就可以通过改变参数来执行敏感操作......
  • 代码随想录算法训练营第28天 | 回溯4:491.递增子序列、46.全排列、47.全排列 II
    代码随想录算法训练营第28天|回溯4:491.递增子序列、46.全排列、47.全排列II491.递增子序列https://leetcode.cn/problems/non-decreasing-subsequences/代码随想录https://programmercarl.com/0491.递增子序列.html#算法公开课46.全排列https://leetcode.cn/problems/pe......
  • 【数据结构】树和二叉树——Lesson1
    Hi~!这里是奋斗的小羊,很荣幸您能阅读我的文章,诚请评论指点,欢迎欢迎~~......
  • 算法力扣刷题记录 五十一【654.最大二叉树】
    前言二叉树篇,继续。记录五十一【654.最大二叉树】一、题目阅读给定一个不重复的整数数组nums。最大二叉树可以用下面的算法从nums递归地构建:创建一个根节点,其值为nums中的最大值。递归地在最大值左边的子数组前缀上构建左子树。递归地在最大值右边的......
  • 算法力扣刷题记录 五十【106.从中序与后序遍历序列构造二叉树】和【105.从前序与中序
    前言记录三十八的四、二叉树构建通过层序遍历的数组实现。层序遍历中,某个节点下标是i,那么左孩子的下标2i+1,右孩子的下标2i+2。这是统一的规律。那么通过中序序列和后序序列如何构造二叉树?通过中序序列和前序序列如何构造二叉树?通过前序序列和后序序列如何构造二叉树?一......
  • [MRCTF2020]Ezpop(反序列化)
    打开题目即可得源码Welcometoindex.php<?php//flagisinflag.php//WTFISTHIS?//LearnFromhttps://ctf.ieki.xyz/library/php.html#%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E9%AD%94%E6%9C%AF%E6%96%B9%E6%B3%95//AndCrackIt!classModifier{protected$var......
  • 从前序与中序遍历序列构造二叉树-递归
    题目描述:个人题解:        只要我们在中序遍历中定位到根节点,那么我们就可以分别知道左子树和右子树中的节点数目。由于同一颗子树的前序遍历和中序遍历的长度显然是相同的,因此我们就可以对应到前序遍历的结果中,对上述形式中的所有左右括号进行定位。这样的话,我们就......
  • wps office 2019 Pro Plus 集成序列号Vba安装版
    前言wpsoffice2019专业增强版含无云版是一款非常方便的办公软件,我们在日常的工作中总会碰到需要使用WPS的时候,它能为我们提供更好的文档编写帮助我们更好的去阅读PDF等多种格式的文档,使用起来非常的快捷方便。使用某银行专业增强版制作,包含vba和Pdf,集成序列号,去除密匙校验,去除......
  • Java二叉树经典例题
    目录一.相同的树二.翻转二叉树三.平衡二叉树四.对称二叉树五.根据前(后)和中序排序构建二叉树1.前序和中序构建2.后序和中序构建六.二叉树的层序遍历七.二叉树非递归遍历1.前序遍历2.中序遍历3.后序遍历八.总结前言:前面说过树是通过递归定义的。做二叉树的题,递......