1.根据二叉树创建字符串?
链接:根据二叉树创建字符串:力扣
??
?
解析:题目是按照前序遍历根,左子树,右子树的遍历方式来存储节点值的。
1(左)(右)?->1((左)(右))((左)(右))。第一种情况不说了,看第二种情况,2的左子树为空,又又子数,但是他的左子树的括号不能省略,你要是省略了就不知道这个4是他的左子树还是右子树。
class Solution {
public:
string tree2str(TreeNode* root) {
if(root==nullptr)
return string();
//空树就返回一个空的string对象就可以了
string str;
str+=to_string(root->val); //根
str+="("; //左子树
str+=tree2str(root->left);
str+=")";
str+="("; //右子树
str+=tree2str(root->right);
str+=")";
return str;
}
};
to_string函数是专门让将数字常量转换为字符串,返回值为转换完毕的字符串。
但是这个还不算完,因为这样我们把所有的括号都打印了,该省去的都打印出来了。
对于左子树来说,左空右空省括号,左空右有(右子树还有数值)不能省,所以只要右子树是空就一定省去括号。
class Solution {
public:
string tree2str(TreeNode* root) {
if(root==nullptr)
return string();
string str;
str+=to_string(root->val);
if(root->left||root->right)
{
str+="(";
str+=tree2str(root->left);
str+=")";
}
if(root->right)
{
str+="(";
str+=tree2str(root->right);
str+=")";
}
return str;
}
};
?2.二叉树分层遍历
二叉树的分层遍历1:力扣?
其实这个用队列解决特别爽,先放根进去,然后放左右子树进去,再把根取出队列,再放进去第三代,然后取出第二代。
但是这个有一个疑问,就比如我们取出根后第二三代都在队列中,咋判断这些数是第二代的还是第三代的?
这里我们用levelSize来记录每一代的个数,那这样即使隔代也能正确出队列了。
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
queue<TreeNode*> q; //创建一个队列
size_t levelSize=0; //记录每一层的实节点个数
if(root) //根不为空,进队列
{
q.push(root);
levelSize=1; // 记录第一代的个数
}
vector<vector<int>> vv;
while(!q.empty())
{
vector<int> v;
for(int i=0;i<levelSize;i++)
{
TreeNode* front=q.front();
q.pop();
v.push_back(front->val);
if(front->left)
{
q.push(front->left);
}
if(front->right)
{
q.push(front->right);
}
}
vv.push_back(v);
levelSize=q.size();
}
return vv;
}
};
- vv:创造的一个二维数组,用来存放二叉树的数据的,他的每一行就是每一代。
- v:? 一维数组,在这个循环里是用来存放每一代的数据的。
- front:用来保存每一个出队列后的数值。
- 当把每一行都给vv之后,改变levelSize使他记录的是下一代的个数。
3.最近公共祖先?
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先:力扣?
?这个题会遇到这三种情况;
p,q分别在根的两边;都在左边;都在右边。
class Solution {
bool Find(TreeNode* sub, TreeNode* x) //查找p,q到底在哪一边
{
if(sub==nullptr)
{
return false;
}
if(sub==x) //找到了
{
return true;
}
return Find(sub->left,x)||Find(sub->right, x);
}
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q)
{
if (root==nullptr)
{
return nullptr;
}
if(root==p||root==q)
{
return root;
}
bool pleft,pright,qleft,qright;
//分别判断p,q到底在哪一边
pleft=Find(root->left, p);
pright=!pleft;
qleft=Find(root->left,q);
qright=!qleft;
//1.p,q在两边
//2.p,q都在左边
//3.p,q都在右边
if((qleft&&pright)||(qright&&pleft))
{
return root;
}
else if(qleft&&pleft)
{
return lowestCommonAncestor(root->left,p,q);
}
else if(qright&&pright)
{
return lowestCommonAncestor(root->right,p,q);
}
else //这种情况一般都走不到
{
return nullptr;
}
}
};
这里的精髓是pleft,pright,qleft,qright。
举个例子,如果p在左子树,那pright就不用找了,如果左子树上没找到,那他一定在右子树那里。
|