代码随想录算法训练营第十八天|112. 路径总和、 113. 路径总和ii、106.从中序与后序遍历序列构造二叉树、105.从前序与中序遍历序列构造二叉树
题解思路和代码:http://www.acwing.com
112. 路径总和
我是一看就会,一写就废。先看代码:
class Solution {
public:
vector<int> path;
bool res;
int Sum = 0;
bool hasPathSum(TreeNode* root, int targetSum) {
res = false;
if(!root) return false;
dfs(root,targetSum);
return res;
}
void dfs(TreeNode* root,int targetSum)
{
if(!root) return;
path.push_back(root->val);
if(!root->left && !root->right)
{
for(int i = 0;i < path.size();i++) Sum += path[i];
if(Sum == targetSum)
{
res = true;
Sum = 0;
}
else
{
Sum = 0;
}
}
else
{
if(root->left) dfs(root->left,targetSum);
if(root->right) dfs(root->right,targetSum);
}
path.pop_back();
}
};
路径总和这道题目,跟前面做的那道输出所有路径的题目十分相似,思想还是回溯的思想,这里说明变量
path:记录每条根到叶子的路径
res:记录返回结果初始值是false(为什么?因为空的情况下就是false,见示例)
Sum:记录路径总和。
首先上来先判断头节点,如果头节点是空的话,直接返回false。然后将当前节点的值加入到path中,然后判断当前的节点是否是叶子节点,如果是的话就直接对这条路径上的所有值进行加和,然后判断最后的Sum值是否等于targetSum,如果等于就让res为true,同时Sum要归零,用来更新下一条路径的和;如果不等,直接让Sum归零就好了。如果不是叶子节点,就一直沿着左右子树走下去,然后将节点的值记录到path中。最后我还是要说一下path.pop()这句话,不是说这个值刚进来然后代码加工一下就出去了,这可不是工厂的机器,原料进去出来就是成品。这里的pop()是递归来的,当某一条路径的值进去后,通过加和对比之后,这一条路径的值再出去。
113. 路径总和ii
先看代码:
class Solution {
public:
vector<int> path;
vector<vector<int>> res;
int Sum = 0;
vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
if(!root) return res;
dfs(root,targetSum);
return res;
}
void dfs(TreeNode* root,int targetSum)
{
if(!root) return;
path.push_back(root->val);
if(!root->left && !root->right)
{
vector<int> line;
for(int i = 0;i < path.size();i++)
{
Sum += path[i];
line.push_back(path[i]);
}
if(Sum == targetSum)
{
Sum = 0;
res.push_back(line);
}
else
{
Sum = 0;
}
}
else
{
if(root->left) dfs(root->left,targetSum);
if(root->right) dfs(root->right,targetSum);
}
path.pop_back();
}
};
这道题目其实和上一道题目是一样的,这里除了加和判断又多加了一条输出路径,这好像是我们前面做过的输出路径和路径和的综合题目,这里就不过多叙述了。
105.从前序与中序遍历序列构造二叉树
先看代码:
class Solution {
public:
unordered_map<int,int> pos;
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
for(int i = 0;i < inorder.size();i++) pos[inorder[i]] = i;
return build(preorder,inorder,0,preorder.size() - 1,0,inorder.size() - 1);
}
TreeNode* build(vector<int>& preorder,vector<int>& inorder,int lp,int rp,int li,int ri)
{
if(lp > rp) return NULL;
TreeNode* root = new TreeNode(preorder[lp]);
int k = pos[root->val];
root->left = build(preorder,inorder,lp + 1,lp + k - li,li,k - 1);
root->right = build(preorder,inorder,lp + k - li + 1,rp,k + 1,ri);
return root;
}
};
先对中序遍历做一下哈希。
106.从中序与后序遍历序列构造二叉树
这道题思路和105一样,大家自己推一下递归区间:
class Solution {
public:
unordered_map<int,int> pos;
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
for(int i = 0;i < inorder.size();i++) pos[inorder[i]] = i;
return build(inorder,postorder,0,inorder.size() - 1,0,postorder.size() - 1);
}
TreeNode* build(vector<int>& inorder,vector<int>& postorder,int li,int ri,int lpos,int rpos)
{
if(li > ri) return NULL;
auto root = new TreeNode(postorder[rpos]);
int k = pos[root->val]; //这里进的不是前序的最开始,也不是后序的最后
root->left = build(inorder,postorder,li,k - 1,lpos,lpos + k - 1 - li);
root->right = build(inorder,postorder,k + 1,ri,lpos + k - 1 - li + 1,rpos - 1);
return root;
}
};