struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode() : val(0), left(NULL), right(NULL) {}
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};
利用递归的思路,一个二叉树的深度实际是其左、右子树的深度的最大值+1;递归终止条件就是根节点为空时,深度为0;有了这个思路,代码就很容易写出来了。
int maxDepth(TreeNode* root){
if(!root)return 0;
return max(maxDepth(root->left),maxDepth(root->right))+1;//需要#include
}
如果不利用递归的话,可以考虑二叉树层序遍历的思路,见链接二叉树的遍历中的第3点的层序遍历输出二维数组的思路,层序遍历的次数就是二叉树的深度了。
int maxDepth(TreeNode* root){
int ans=0;
if(!root)return ans;
queue<TreeNode*>q;
q.push(root);
int size=1;//表示每层的叶子节点的个数
while(!q.empty()){
ans++;//每遍历一次,二叉树的层数+1
int size=q.size();
for(int i=0;i<size;i++){
if(q.front()->left)q.push(q.front()->left);
if(q.front()->right)q.push(q.front()->right);
q.pop();
}
}
return ans;
}
LeetCode100.相同的树
若是用递归,思路就是两棵树根节点相同且左右子树都相同才是相同的,终止条件要考虑根节点为空的情况,若函数输入的两个节点均为空,返回真;一个为空另一个不为空,返回假,代码如下:
bool isSameTree(TreeNode* p, TreeNode* q) {
if(p&&!q)return false;//一个为空一个不为空,不相同
if(!p&&q)return false;//同上
if(!p&&!q)return true;//两个均为空,相同
return (p->val==q->val) && isSameTree(p->left,q->left) && isSameTree(p->right,q->right);//根节点相同且左右子树相同,则两个二叉树是相同的
}
非递归的思路依旧可以参照二叉树的层序遍历,利用两个队列,模拟层序遍历,每次循环的队首元素都要相同,注意需要多考虑一边节点为空另一边节点不空的情况。
注意:其实有空间上更优的方法,用一个队列即可,代码附在这种方法的后面。
bool isSameTree(TreeNode* p, TreeNode* q) {
queue<TreeNode*>pp;
queue<TreeNode*>qq;
if(!q&&!p)return true;//均为空树,返回真
if(q&&!p)return false;//一个为空树,一个不为空树,返回假
if(!q&&p)return false;//一个为空树,一个不为空树,返回假
qq.push(q);
pp.push(p);
while(!qq.empty() && !pp.empty()){
bool qqleft=qq.front()->left==NULL;
bool qqright=qq.front()->right==NULL;
bool ppleft=pp.front()->left==NULL;
bool ppright=pp.front()->right==NULL;
if(qqleft^ppleft)return false;//若两队首元素的左节点一个为空一个非空,返回假
if(qqright^ppright)return false;//若两队首元素的右节点一个为空一个非空,返回假
if(qq.front()->val!=pp.front()->val)return false;
if(qq.front()->left)qq.push(qq.front()->left);
if(qq.front()->right)qq.push(qq.front()->right);
qq.pop();
if(pp.front()->left)pp.push(pp.front()->left);
if(pp.front()->right)pp.push(pp.front()->right);
pp.pop();
}
return true;
}
更优的方法只需要用一个队列即可,每次将两个二叉树的对应位置的节点依次入队,对比后再依次出队。
bool isSameTree(TreeNode *u, TreeNode *v) {
queue <TreeNode*> q;
q.push(u);
q.push(v);
while (!q.empty()) {
u = q.front();
q.pop();
v = q.front();
q.pop();
if (!u && !v) continue;//当两个二叉树的节点均为空时,跳过当前的循环
if ((!u || !v) || (u->val != v->val)) return false;//当二叉树对应位置一个树为空节点另一个树不是空节点时,当对应位置的元素不相等时,都不相同,返回假。
q.push(u->left);
q.push(v->left);
q.push(u->right);
q.push(v->right);
}
return true;
}
LeetCode101.对称二叉树
递归的思路和上一题的判断两棵树是否相同非常类似,判断二叉树是否镜像对称就是判断左子树和右子树是否对称,与上一题在代码上的区别只是参数是左、右子树。
bool isSymmetric_help(TreeNode* p,TreeNode* q) {
if(p&&!q)return false;
if(!p&&q)return false;
if(!p&&!q)return true;
return (p->val==q->val) && isSymmetric_help(p->left,q->right) && isSymmetric_help(p->right,q->left);
}
bool isSymmetric(TreeNode* root) {
if(!root)return false;
return isSymmetric_help(root->left,root->right);
}
非递归的思路依旧可以参照二叉树的层序遍历,依照判断二叉树是否相同的第三种思路,代码逻辑非常类似,交换一下节点的入栈的顺序,即可。
bool isSymmetric_help(TreeNode *u, TreeNode *v) {
queue <TreeNode*> q;
q.push(u); q.push(v);
while (!q.empty()) {
u = q.front();
q.pop();
v = q.front();
q.pop();
if (!u && !v) continue;
if ((!u || !v) || (u->val != v->val)) return false;
q.push(u->left);
q.push(v->right);
q.push(u->right);
q.push(v->left);
}
return true;
}
bool isSymmetric(TreeNode* root) {
return isSymmetric_help(root, root);
}
LeetCode226.翻转二叉树
直接用递归即可,每次左右节点交换。
TreeNode* invertTree(TreeNode* root) {
if(root==NULL)return NULL;
TreeNode* left = invertTree(root->left);
TreeNode* right = invertTree(root->right);
root->left = right;
root->right = left;
return root;
}
LeetCode617.合并二叉树
和上一题很像,利用递归的方法。
TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) {
if (!t1) return t2;
if (!t2 ) return t1;
TreeNode* merged = new TreeNode(t1->val + t2->val);
merged->left = mergeTrees(t1->left, t2->left);
merged->right = mergeTrees(t1->right, t2->right);
return merged;
}
LeetCode110.平衡二叉树
平衡二叉树的定义是,一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。
关于二叉树的高度计算,借助题目1的递归最为方便。
int depth(TreeNode* root) {
if (root == NULL) return 0;
return max(depth(root->left), depth(root->right)) + 1;
}
bool isBalanced(TreeNode* root) {
if (root == NULL) return true;
return abs(depth(root->left) - depth(root->right)) <= 1 && isBalanced(root->left) && isBalanced(root->right);
}
这个方法,因此对于同一个节点,求二叉树深度的函数depth会被重复调用,导致时间复杂度较高。如果使用自底向上的做法,可以做到每次depth函数只被调用一次。
自底向上递归的做法类似于后序遍历,对于当前遍历到的节点,先递归地判断其左右子树是否平衡,再判断以当前节点为根的子树是否平衡。如果一棵子树是平衡的,则返回其高度(高度一定是非负整数),否则返回 −1-1−1。如果存在一棵子树不平衡,则整个二叉树一定不平衡。
int height(TreeNode* root) {
if (root == NULL)return 0;
int leftHeight = height(root->left);
int rightHeight = height(root->right);
if (leftHeight == -1 || rightHeight == -1 || abs(leftHeight - rightHeight) > 1) return -1;
return max(leftHeight, rightHeight) + 1;
}
bool isBalanced(TreeNode* root) {
return height(root) >= 0;
}