513.找树左下角的树
思路:利用递归遍历,后序遍历的顺序(前中后序都可以,因为都是先左后右),当遍历到叶子节点时,记录深度,如果比之前记录的深度更深则更新深度,和最深的叶子节点的值,遍历所有结点后,返回值。
class Solution {
public:
int result;
int maxDepth = INT_MIN;
void getleftnum(TreeNode*root,int depth)
{
if(root->left==NULL&&root->right==NULL)//叶子节点就返回
{
if(depth>maxDepth)
{
maxDepth = depth;
result = root->val;
}
return;
}
if(root->left)
{
depth++;
getleftnum(root->left,depth);
depth--;//回溯
}
if(root->right)
{
depth++;
getleftnum(root->right,depth);
depth--;
}
return;
}
int findBottomLeftValue(TreeNode* root) {
getleftnum(root,1);
return result;
}
};
112.路径总和
思路:利用递归遍历,当遍历到叶子节点时,判断targetSum值是否为0,如果为0,说明该条路径为满足条件的路径,直接返回true,如果遍历所有节点都没有满足条件的路径,则返回false。每向下遍历时,targetSum减去对应节点的值。 回溯。
class Solution {
public:
bool traversal(TreeNode* root, int targetSum)
{
if(root->left==NULL&&root->right==NULL&&targetSum==0)
{
return true;
}
if(root->left==NULL&&root->right==NULL&&targetSum!=0)
{
return false;
}
if(root->left)
{
targetSum-=root->left->val;
if(traversal(root->left,targetSum))
{
return true;
}
targetSum+=root->left->val;
}
if(root->right)
{
targetSum-=root->right->val;
if(traversal(root->right,targetSum))
{
return true;
}
targetSum+=root->right->val;
}
return false;
}
bool hasPathSum(TreeNode* root, int targetSum) {
//递归
if(root==NULL)
{
return false;
}
return traversal(root,targetSum-root->val);
}
};
113.路径总和II
思路:题目要返回满足条件的路径集合,则建立全局变量vector<vector<int>> result,vector<int> path。path用来记录路径节点,result用来存放满足条件的path。利用递归遍历,同上一题,只不过在单层遍历中,向下遍历时向path输入当前节点的值,回溯时也要推出这个值。当遍历到叶子节点时,如果targetSum=0,就把path输入result。遍历所有结点后,返回result。
class Solution {
public:
vector<vector<int>> result;
vector<int> path;
void traversal(TreeNode*root,int targetSum)
{
if(root->left==NULL&&root->right==NULL&&targetSum==0)
{
result.push_back(path);
return;
}
if(root->left==NULL&&root->right==NULL&&targetSum!=0)
{
return;
}
if(root->left)
{
path.push_back(root->left->val);
targetSum-=root->left->val;
traversal(root->left,targetSum);
targetSum+=root->left->val;
path.pop_back();
}
if(root->right)
{
path.push_back(root->right->val);
targetSum-=root->right->val;
traversal(root->right,targetSum);
targetSum+=root->right->val;
path.pop_back();
}
return;
}
vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
if(root==NULL)
{
return result;
}
path.push_back(root->val);
traversal(root,targetSum- root->val);
return result;
}
};
106.从中序与后序遍历序列构造二叉树
思路:后序遍历序列的最后一个节点为当前层的根节点,前面的序列分为左树序列和右树序列。利用递归遍历,当中序和后序序列的大小都为0时,说明二叉树构造完毕,返回root。先在后序序列中找到当前层的根节点,然后在中序序列中分割出来中序左树序列和中序右树序列,然后根据左树序列的大小,在后序序列中分割出来后序左树序列和后序右树序列。当前层的根节点的左右子节点分别为下一层递归得到的节点。
class Solution {
public:
TreeNode* traversal(vector<int>& inorder, vector<int>& postorder) {
//如果后序数组大小为零,说明是空数组
if(postorder.size()==0)
{
return NULL;
}
//后序数组最后一个元素为根节点
int rootvalue = postorder[postorder.size()-1];
TreeNode* root = new TreeNode(rootvalue);
//如果后序遍历数组大小为1,说明是叶子节点
if(postorder.size()==1)
{
return root;
}
//找切割点
int delimiterIndex;
for(delimiterIndex=0;delimiterIndex<inorder.size();delimiterIndex++)
{
if(inorder[delimiterIndex]==root->val)
{
break;
}
}
//切割中序数组,得到中序左数组和中序右数组
vector<int> midleft;
vector<int> midright;
for(int i =0;i<delimiterIndex;i++)
{
midleft.push_back(inorder[i]);
}
for(int i =delimiterIndex+1;i<inorder.size();i++)
{
midright.push_back(inorder[i]);
}
//切割后序数组,得到后序左数组和后序右数组
vector<int> posleft;
vector<int> posright;
for(int i = 0;i<midleft.size();i++)
{
posleft.push_back(postorder[i]);
}
for(int i = midleft.size();i<postorder.size()-1;i++)
{
posright.push_back(postorder[i]);
}
root->left = traversal(midleft,posleft);
root->right = traversal(midright,posright);
return root;
}
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
if(inorder.size()==0||postorder.size()==0)
{
return NULL;
}
return traversal(inorder,postorder);
}
};
105.从前序与中序遍历序列构造二叉树
思路:与上一题思路相同,只不过这次根节点的判断在前序的第一个元素,因此分割的方式也会有所改变。
class Solution {
public:
TreeNode* traversal(vector<int>& preorder, vector<int>& inorder)
{
if(preorder.size()==0)
{
return NULL;
}
int rootnum = preorder[0];
TreeNode *root = new TreeNode(rootnum);
if(preorder.size()==1)
{
return root;
}
int index;
for( index = 0;index<inorder.size();index++)
{
if(inorder[index]==rootnum)
{
break;
}
}
vector<int> midleft;
vector<int> midright;
//中序左数组
for(int i =0;i<index;i++)
{
midleft.push_back(inorder[i]);
}
//中序右数组
for(int i = index+1;i<inorder.size();i++)
{
midright.push_back(inorder[i]);
}
vector<int> preleft;
vector<int> preright;
//先序左数组
for(int i =0;i<midleft.size();i++)
{
preleft.push_back(preorder[i+1]);
}
//先序右数组
for(int i=midleft.size()+1;i<preorder.size();i++)
{
preright.push_back(preorder[i]);
}
root->left = traversal(preleft,midleft);
root->right = traversal(preright,midright);
return root;
}
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
if(preorder.size()==0||inorder.size()==0)
{
return NULL;
}
return traversal(preorder,inorder);
}
};
收获:
逐渐理解回溯。
熟练使用递归。