??经典二叉树问题,快乐是要保证的。
二叉树的最大深度
??典中典之二叉树最大深度,非常经典的深度搜索和递归。 ??对左右子树深度搜索,如果碰到空节点就返回,每次返回计数都+1,最后在左子树和右子树中取最大值。
class Solution {
public:
int maxDepth(TreeNode* root) {
if(root==nullptr) return 0;
return max(maxDepth(root->left),maxDepth(root->right))+1;
}
};
对称二叉树
??如果是判断对称的话,其实是迭代的思路比较好想。
class Solution {
public:
bool mirrorTest(TreeNode* u,TreeNode* v){
queue<TreeNode*> queue1;
queue1.push(u);
queue1.push(v);
while(!queue1.empty()){
u=queue1.front();
queue1.pop();
v=queue1.front();
queue1.pop();
if(u==nullptr&&v==nullptr) continue;
if((!u||!v)||(u->val!=v->val)) return false;
queue1.push(u->left);
queue1.push(v->right);
queue1.push(u->right);
queue1.push(v->left);
}
return true;
}
bool isSymmetric(TreeNode* root) {
return mirrorTest(root,root);
}
};
??我们再使用一下深度搜索:
class Solution {
public:
bool isSymmetric(TreeNode* root) {
return compare(root->left,root->right);
}
bool compare(TreeNode* node1,TreeNode* node2){
if(node1==nullptr&&node2==nullptr){
return true;
}
if(node1==nullptr||node2==nullptr||node1->val != node2->val){
return false;
}
return compare(node1->left,node2->right)&&compare(node1->right,node2->left);
}
};
翻转二叉树
??翻转二叉树是一个经典的前序遍历递归,是从根节点向下递归的。
class Solution {
public:
TreeNode* invertTree(TreeNode* root) {
if(root==nullptr) return nullptr;
swap(root->left,root->right);
invertTree(root->left);
invertTree(root->right);
return root;
}
};
二叉树的直径
??这个直径题容易让人摸不清头脑。 ??首先这个最大直径应该是时刻更新的,所以关键在于直径怎么表达。 ??某个节点的直径等于该节点左子树的高度 + 右子树的高度。 ??问题一下子分解成了:求每个点的高度+计算直径更新答案。
class Solution {
public:
int res = 0;
int dfs(TreeNode* root){
if(root == nullptr){
return 0;
}
int left = dfs(root->left);
int right = dfs(root->right);
res = max(res,left+right);
return max(left,right) + 1;
}
int diameterOfBinaryTree(TreeNode* root) {
dfs(root);
return res;
}
};
剑指 Offer 27. 二叉树的镜像
??其实和翻转二叉树是一个题。
class Solution {
public:
TreeNode* mirrorTree(TreeNode* root) {
if(root == NULL) return NULL;
swap(root->left,root->right);
mirrorTree(root->left);
mirrorTree(root->right);
return root;
}
};
平衡二叉树
??平衡二叉树还是比较有意思的,说白了,对于任何一个节点来说,该节点的左右子树高度差不能超过1,而且左右子节点都应该满足这个条件。 ??这条件也太递归了,同时我们注意这里要求节点的高度,这个求高度和判断平衡二叉树是无耦合的,我们可以拆出来写。
class Solution {
public:
int getheight(TreeNode* node){
if(node == nullptr) return 0;
return max(getheight(node->left),getheight(node->right)) + 1;
}
bool isBalanced(TreeNode* root) {
if(root==nullptr){
return true;
}
return abs(getheight(root->left)-getheight(root->right)) <=1&&isBalanced(root->left)&&isBalanced(root->right);
}
};
合并二叉树
??合并二叉树算是比较有趣的问题了,当然一看就知道是递归。 ??注意我们要合并一个新的二叉树,也就是说每个节点在递归的时候,我们要为它创建一个新节点。 ??我们这次用递归三部曲来想一下。 ??终止条件是什么?当两个二叉树对应节点有空的时候返回另外一个。 ??每一次递归return什么?因为我们每次递归到一个节点都要创建一个新节点,所以我们每次要把这个新节点给返回来。 ??每一次递归操作什么?创建一个新节点,赋值,这还没完,需要为其配上左子节点和右子节点,配左子节点和右子节点就实现了递归。
class Solution {
public:
TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
if(root1==nullptr) return root2;
if(root2==nullptr) return root1;
TreeNode* node = new TreeNode(0);
node->val = root1->val + root2->val;
node->left = mergeTrees(root1->left,root2->left);
node->right = mergeTrees(root1->right,root2->right);
return node;
}
};
二叉树的所有路径
??从这个题开始出现了“路径”一词。 ??刷题有经验就会意识到,是不是该搜索了。 ??再仔细一看提供的标准输入输出,完全可以确定是个深度优先搜索问题。
class Solution {
public:
void dfs(TreeNode* root,vector<string>& res,string temp){
if(temp==""){
temp += to_string(root->val);
}else{
temp +="->";
temp += to_string(root->val);
}
if(root->left==nullptr&&root->right==nullptr){
res.push_back(temp);
return;
}
if(root->left) dfs(root->left,res,temp);
if(root->right) dfs(root->right,res,temp);
}
vector<string> binaryTreePaths(TreeNode* root) {
vector<string> result;
if(root==nullptr) return result;
dfs(root,result,"");
return result;
}
};
剑指 Offer 68 - II. 二叉树的最近公共祖先
??我们要找两个节点的祖先,是不是应该从底往上找?所以该题是明显的后序遍历。 ??清楚是后续遍历之后,我们去模拟寻找p和q的过程。 ??如果寻找到了q或者p,就立刻返回,因为我们要祖先,肯定要上找。。 ??如果该节点不是p或者q,就利用后序遍历从左右子树中去寻找,再根据左右子树寻找结果来判断公共祖先应该是自己,还是在左子树,还是在右子树。
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if(root == NULL||root == p||root == q){
return root;
}
TreeNode* left = lowestCommonAncestor(root->left,p,q);
TreeNode* right = lowestCommonAncestor(root->right,p,q);
if(!left) return right;
if(!right) return left;
return root;
}
};
|