day 16
day 16|完全二叉树的节点个数 路径综合 从中序与后序遍历序列构造二叉树
222.完全二叉树的节点个数
笔记
利用完全二叉树的特性,如果一个树是满二叉树,他的节点个数能够根据他的最大深度求出。
怎么判断一个树是否为满二叉树?(在已知这个树肯定是完全二叉树的情况下)他的最左端的节点和最右端的节点深度相同。
1.递归传入参数和输出参数:传入参数为根节点、输出参数为总节点个数
2.截止条件:碰到nullptr直接返回0;如果是满二叉树,直接返回2^n-1(n是深度);
3.单层递归逻辑:向左向右递归求得左右子树的节点个数;在中间节点返回该树的总结点个数(左+右+1);
实操出现问题
位操作优先级低于加减法
2<<leftdepth-1等价于2 << (leftdepth - 1)
为了保证不移动负数位,应该加括号(2<<leftdepth)-1;
代码/比较
class Solution {
public:
int countNodes(TreeNode* root) {
//截止条件:1.null 2.满二叉树
if(root==nullptr) return 0;
int leftdepth=0;
int rightdepth=0;
TreeNode* root_left=root;
while(root_left->left)
{
root_left=root_left->left;
leftdepth++;
}
TreeNode* root_right=root;
while(root_right->right)
{
root_right=root_right->right;
rightdepth++;
}
if(rightdepth==leftdepth)
return (2<<leftdepth)-1;
//单层递归逻辑:
return (countNodes(root->left)+countNodes(root->right)+1);
}
};
112. 路径总和
笔记:
1.传入参数和输出参数:输出true/false,传入根节点、对比值;
2.截止条件:如果是叶子节点并且对比值为0;返回true;
3.单层递归逻辑:分别向左右遍历,用对比值减去当前节点的val值传入下一个递归,如果返回的是true则向上返回true;
实操出现问题:
对于叶子节点应该先减去自己的值来对比。
代码:
class Solution {
public:
bool hasPathSum(TreeNode* root, int targetSum) {
//截止条件:如果是叶子节点并且对比值为0,返回true;如果找到叶子但是对比值不为0,返回false
if(root==nullptr) return false;
if(root->left==nullptr&&root->right==nullptr&&targetSum-root->val==0) return true;
if(root->left==nullptr&&root->right==nullptr&&targetSum-root->val!=0) return false;
//单层循环逻辑:分别向左右遍历,用对比值减去当前节点的val值传入下一个递归,如果返回的是true则向上返回true;
if(root->left)
{
if(hasPathSum(root->left,targetSum-root->val))
return true;
}
if(root->right)
{
if(hasPathSum(root->right,targetSum-root->val))
return true;
}
return false;
}
};
113.路径总和2
自己的思考:
1.传入参数:root和对比值。输出参数:无。但是要用全局变量,一个一维数组,一个二维数组,一维数组用于存放当前路径,二维数组用于存放结果路径。
2.截止条件:如果是叶子节点并且对比值为0,将当前一维数组push_back到二维数组中,return;如果不为0,不做任何处理,return即可。
3.单层迭代逻辑:依次向左右子树进行递归求对比值,同时将下一个路径放入一维数组中
代码:
class Solution {
public:
vector<int> result_1;
vector<vector<int>> result_2;
void traversal(TreeNode* root,int targetSum)
{
//截止条件:如果是叶子节点并且对比值为0,将当前一维数组`push_back`到二维数组中,`return`;如果不为0,不做任何处理,`return`即可。
if(root->left==nullptr&&root->right==nullptr&&targetSum-root->val==0)
{
result_2.push_back(result_1);
return;
}
if(root->left==nullptr&&root->right==nullptr&&targetSum-root->val!=0)
return;
//单层递归逻辑:依次向左右子树进行递归求对比值,同时将下一层路径放入一维数组中
if(root->left)
{
result_1.push_back(root->left->val);
traversal(root->left,targetSum-root->val);
result_1.pop_back();
}
if(root->right)
{
result_1.push_back(root->right->val);
traversal(root->right,targetSum-root->val);
result_1.pop_back();
}
return ;
}
vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
result_2.clear();
if(root==nullptr) return result_2;
//先把现在的路径传入result_1
result_1.push_back(root->val);
traversal(root,targetSum);
return result_2;
}
};
106.从中序与后序遍历序列构造二叉树
- 第一步:如果数组大小为零的话,说明是空节点了。
- 第二步:如果不为空,那么取后序数组最后一个元素作为节点元素。
- 第三步:找到后序数组最后一个元素在中序数组的位置,作为切割点
- 第四步:切割中序数组,切成中序左数组和中序右数组 (顺序别搞反了,一定是先切中序数组)
- 第五步:切割后序数组,切成后序左数组和后序右数组
- 第六步:递归处理左区间和右区间
中间切割数组的时候要注意循环不变量,即按照一个规则进行切割。
代码(明天补上):
class Solution {
public:
//传入参数:中序数组和后续数组 输出参数:根节点
TreeNode* traversal(vector<int>& inorder,vector<int>& postorder)
{
//截止条件:如果后序数组为空(因为先切后序数组),则返回空节点;创建中间节点;如果碰到叶子节点,则返回当前的节点;
if(postorder.size()==0) return nullptr;
int val=postorder[postorder.size()-1];//后序遍历最后一个一定是中节点
TreeNode* root=new TreeNode(val);
//if(postorder.size()==1) return root;
//每层递归的逻辑:得到左子树的中序和后序数组、右子树的中序和后序数组;再依次遍历左右子树
//找中序数组的分割点
int index=0;
for(;index<inorder.size();index++)
{
if(inorder[index]==val)
break;
}
//将中序数组分割为左右子树的中序数组,注意左闭右开;
vector<int> left_inorder(inorder.begin(),inorder.begin()+index);
vector<int> right_inorder(inorder.begin()+index+1,inorder.end());
//将后序数组分割为左右子树的后序数组,注意左闭右开;
postorder.resize(postorder.size()-1);
vector<int> left_postorder(postorder.begin(),postorder.begin()+index);
vector<int> right_postorder(postorder.begin()+index,postorder.end());
//再依次遍历左右子树
root->left = traversal(left_inorder, left_postorder);
root->right = traversal(right_inorder, right_postorder);
return root;
}
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
if (inorder.size() == 0 || postorder.size() == 0) return NULL;
return traversal(inorder, postorder);
}
};
1

浙公网安备 33010602011771号