第一次做没做出来,看了卡哥的视频,我很疑惑:翻转和前中后序遍历有什么关系呢?其实,所谓的遍历顺序,也就是处理的顺序,其目的不在于把它遍历出来,而是给出一个等待处理的顺序或者说将二叉树转换成了类似于数组的结构,数组内的元素就按二叉树的前中后序来排列,这样就能使得二叉树的结点能够有序地被处理。具体代码如下:
class Solution {
public:
TreeNode* invertTree(TreeNode* root) {
if(root==nullptr)
return root;
swap(root->left,root->right);
invertTree(root->left);
invertTree(root->right);
return root;
}
};
用前序遍历的方式来有序地获取二叉树的元素。
有一点需要注意,root既是根节点,又是函数的参数。实际上的root一直待在原位,根本没有移动(根节点显然是不应该移动的);而root又作为参数,在形式上好像是一个指针,跟随来到各个结点。其实,对于非根结点来说,root只是一个形参,实参还是这个结点本身。而root的实参一直都是根节点,而不过是作为形参被各个结点借用。所以,只有在第一次递归的时候,root才是真实的root,其他时候都是其他结点的形参。
对于swap()函数,应该默认不限制数据类型。
另外,后序遍历,只是改了一下swap的位置:
invertTree(root->left);
invertTree(root->right);、
swap(root->left,root->right);
而中序遍历就不一样了,两个都是left(自己思考过程):
invertTree(root->left);
swap(root->left,root->right);
invertTree(root->left);
对于收集孩子信息,向上一层返回的题目,我们需要用后续遍历:
class Solution {
public:
bool compare(TreeNode*left,TreeNode*right)
{
if(left==nullptr&&right!=nullptr)
return false;
else if(left!=nullptr&&right==nullptr)
return false;
else if(left==nullptr&&right==nullptr)
return true;
else if(left->val!=right->val)
return false;
bool outside=compare(left->left,right->right);
bool inside=compare(left->right,right->left);
return outside&&inside;
}
bool isSymmetric(TreeNode* root) {
if(root!=nullptr)
return compare(root->left,root->right);
else
return false;
}
};
总体思路:采用递归的方式,三步走:
理解了上面的题目,这道题就不是很难了,第一次就做出来了。具体代码如下:
class Solution {
public:
void countNumber(TreeNode* root,int &count)
{
if(root==nullptr)
return;
count++;
int count1=count,count2=count;
countNumber(root->left,count1);
countNumber(root->right,count2);
count=count1>count2?count1:count2;
}
int maxDepth(TreeNode* root) {
int count=0;
if(root!=nullptr)
countNumber(root,count);
return count;
}
};
总体思路:采用递归的方式,三步走即可。这题依然是后序,需要先让左右孩子递归,得到它们的节点值,然后往上传递给当前值。
比最大深度稍微难了点,具体代码如下:
class Solution {
public:
void countNumber(TreeNode* root,int&count)
{
if(root==nullptr)
return;
count++;
int count1=count,count2=count;
countNumber(root->left,count1);
countNumber(root->right,count2);
if(count1==count&&count2!=count)
count=count2;
else if(count2==count&&count1!=count)
count=count1;
else if(count1==count&&count2==count)
return;
else
count=count1<count2?count1:count2;
}
int minDepth(TreeNode* root) {
int count=0;
if(root!=nullptr)
countNumber(root,count);
return count;
}
};
与求最大深度相比,求最小深度不同之处在于——需要判断其左孩子或有孩子是否为空。如果是空的,说明这一侧没有孩子节点了,所以只能取另一侧的count值。只有当两侧都不为空,我们才能取两个count中的最小值作为当前结点的结果,而求最大深度是不需要考虑这些问题的。