力扣222、完全二叉树的节点数量(补上昨天代码)
说明:昨天分析过用完全二叉树的特性这挑一侧进行遍历去进行分析后,代码用的是普通二叉树后序遍历实现的统计,这里再把用完全二叉树特性的代码补上。
代码:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
int getNodesNum(TreeNode* cur){
if(cur==nullptr)return 0;
TreeNode* left=cur->left;
TreeNode* right=cur->right;
int lefthight=0;
int righthight=0;
while(left){
left=left->left;
lefthight++;
}
while(right){
right=right->right;
righthight++;
}
if(lefthight==righthight){
return (2<<lefthight)-1;
}
return getNodesNum(cur->left)+getNodesNum(cur->right)+1;//不相等,从源节点往下数
}
int countNodes(TreeNode* root) {
return getNodesNum(root);
}
};
力扣110、平衡二叉树
定义:所谓平衡二叉树,就是二叉树的左子树和右子树的高度差的绝对值不超过1的二叉树。
思路:
要判断一棵二叉树是否是平衡二叉树,只要它的任意一棵子树不是平衡二叉树,那么这棵二叉树就不可能成为平衡二叉树。
KEY:左右子树的高度差应该用绝对值括起来。
总结:从上述分析中不难看出,要判断一棵树是否为平衡二叉树,可以从下往上判断,只要任意一棵子树不是平衡二叉树,那么这棵树就不可能是平衡二叉树,这种从下往上判断的方式很适合用后序遍历来实现,故而代码如下。
代码:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
int getHeight(TreeNode* node){
if(node==nullptr)return 0;
int leftHeight=getHeight(node->left);//左
if(leftHeight==-1)return -1;
int rightHeight=getHeight(node->right);//右
if(rightHeight==-1)return -1;
int result;
if(abs(leftHeight-rightHeight)>1){
result= -1;
}else{
result=max(leftHeight,rightHeight)+1;
}
return result;
}
bool isBalanced(TreeNode* root) {
return getHeight(root)==-1?false:true;
}
};
力扣、257二叉树的所有路径
思路:要想找出一棵树的路径,实际上是要往深处钻,并且既然要求的是路径,那么访问节点的顺序和记录也就是处理节点的顺序应该保持一致,前序遍历就很好的满足这两点,故而可以用前序遍历来记录路径
本题还有另外一个问题,那就是要取到所有路径,这就要求当我们找到一条路径后不能停止,要回溯到上面的节点继续搜寻是否有其他的路径,因此本题还要用到回溯的思想方法。
这里要特别注意,回溯和递归一定是一一对应的,它们永远在一起,世界上最远的距离便是你在花括号里递归,我在花括号外回溯。
其他注意事项:不要忘了叶子节点也是要加入路径的,因此对中间节点的处理应当放在保存路径之前。
总结:综上所述,那么按照递归三部曲,首先我们要传入的参数应该有根节点,保存路径的数组(vector),保存结果集的数组(vector),这里用vector来保存路径是为了便于回溯。
其次,递归的终止条件,当我们走到叶子节点时,我们就应该保存当前路径并将该结果放入结果集中了。
最后,用前序遍历的方式和回溯的思想处理好每层逻辑,只要有递归,就一定要同时回溯。
代码:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
int getHeight(TreeNode* node){
if(node==nullptr)return 0;
int leftHeight=getHeight(node->left);//左
if(leftHeight==-1)return -1;
int rightHeight=getHeight(node->right);//右
if(rightHeight==-1)return -1;
int result;
if(abs(leftHeight-rightHeight)>1){
result= -1;
}else{
result=max(leftHeight,rightHeight)+1;
}
return result;
}
bool isBalanced(TreeNode* root) {
return getHeight(root)==-1?false:true;
}
};
力扣404、左叶子之和
分析:要求二叉树中所有左叶子节点的和,首先要明确左叶子节点的定义:它指的是当节点A的左孩子不为空,并且节点A的左孩子的左右孩子均为空时,那么节点A的左孩子节点就称为左叶子节点。因此,我们要判断一个节点是否是左孩子节点,就必须要通过该节点的父节点才能够完成判定。
思路:要求左叶子节点之和,我们就要从下往上把左叶子节点的值逐层累加起来,这种从下往上处理节点的手法我们已经做过很多题了,应该用后序遍历来实现,本题的参数和返回值已经给出,我们接下来考虑递归的终止条件就好,实际上刚刚在分析中我们就已经得出结论了:当一个节点它的左孩子节点不为空,并且它的左孩子的左右孩子均为空时,该节点的左孩子节点就是左叶子节点,这时我们就可以拿到左叶子节点的数值,并且向上返回该棵子树的左叶子节点的值,还有一种情况,就是节点为空和节点的左右孩子均为空的时候,那么这时该子树就没有左叶子节点,返回0就可以了,这就是递归终止的条件。最后我们再看看每层的处理逻辑是怎样的:本题要不断将求和的结果向上返回,因此毫无疑问可以用后序遍历的递归法来实现,而每层的中间节点的值应当为左子树和右子树各自的左叶子之和的和。
总结:本题的关键就是要明确:必须通过父节点来找到左叶子节点。
代码:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
int sumOfLeftLeaves(TreeNode* root) {
//因为要求左叶子之和要不断向上返回数值,因此采用后序遍历代码会更简洁一些
if(root==nullptr)return 0;
if(root->left==nullptr&&root->right==nullptr)return 0;
int leftValue=sumOfLeftLeaves(root->left);//左
if(root->left&&root->left->left==nullptr&&root->left->right==nullptr){
leftValue=root->left->val;
}
int rightValue=sumOfLeftLeaves(root->right);//右
return leftValue+rightValue;//中
}
};