文章目录
- 二叉树创建字符串
- 二叉树分层遍历(从前开始)
- 二叉树分层遍历(从后开始)
- 二叉树的最近公共祖先
- 二叉搜索树与双向链表
- 从前序与中序遍历序列构造二叉树
- 从中序与后序遍历序列构造二叉树
- 二叉树的前序遍历(非递归)
- 二叉树的中序遍历(非递归)
- 二叉树的后续遍历
二叉树创建字符串
思路: 该题需要注意的细节就是当节点的左子树为空,而右子树却不为空的情况,就需要特殊处理,也是需要加上
()
,而节点的左子树不为空,右子树为空就是不需要加上()
。if(root->left||root->right)
该语句就是实现左子树的字符和()
,之后再去处理右子树。
//C++
class Solution {
public:
string tree2str(TreeNode* root) {
if(root==nullptr)
{
return "";
}
string 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;
}
};
二叉树分层遍历(从前开始)
**思路:**创建一个队列,将遍历的数据存入到里面,在创建一个计数器用来记录每层的数据个数。
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
queue<TreeNode*> q;
vector<vector<int>> vv;
int levelsize=0;
if(root)
{
q.push(root);
levelsize=1;
}
while(!q.empty())
{
vector<int> v;
while(levelsize--)
{
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;
}
};
二叉树分层遍历(从后开始)
**思路:**其实他就和上一个题的思路是一样的,只需要加个翻转就可以了。
class Solution {
public:
vector<vector<int>> levelOrderBottom(TreeNode* root) {
queue<TreeNode*> q;
vector<vector<int>> vv;
int levelsize=0;
if(root)
{
q.push(root);
levelsize=1;
}
while(!q.empty())
{
vector<int> v;
while(levelsize--)
{
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();
}
reverse(vv.begin(),vv.end());
return vv;
}
};
二叉树的最近公共祖先
思路:
1、使用三叉链(有父节点)转换为链表相交问题,其中长的一条先走gap。
2、就是进行判断确定一个数在自己的左边,另一个在自己的右边。不在用一边就说明现在的节点就是最近的公共祖先,在同一边就需要继续向下找。
class Solution {
public:
bool Isintree(TreeNode* root,TreeNode* in)
{
if(root==nullptr)
{
return false;
}
if(root==in)
{
return true;
}
else
{
return Isintree(root->left,in) || Isintree(root->right,in);
}
}
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if(root==nullptr)
{
return nullptr;
}
if(p==root || q==root)
{
return root;
}
bool pinleft=Isintree(root->left,p);
bool pinright=!pinleft;
bool qinleft=Isintree(root->left,q);
bool qinright=!qinleft;
if((pinleft && qinright) || (pinright && qinleft))
{
return root;
}
else if(pinleft&&qinleft)
{
return lowestCommonAncestor(root->left,p,q);
}
else
{
return lowestCommonAncestor(root->right,p,q);
}
}
};
注意: 上面的写法是属于性能较低的,他所用的时间是较长的。时间复杂度是
O(N^2)
。在他最坏的情况下会出现歪脖子树。也就是确定一次两个数在哪边(递归一边查找,歪脖子树),共要向下递归N次。
思路: 下面的思路就是找到两条路径,用找链表的公共节点的方法来找最近公共节点。需要注意的就是在放入栈之后要进行判断下面没有就要进行出栈。
class Solution {
public:
bool Getpath(TreeNode* root, TreeNode* g,stack<TreeNode*>& path)
{
if(root==nullptr)
{
return false;
}
path.push(root);//只要不是空就放进来
if(root==g)
{
return true;
}
if(Getpath(root->left,g,path))
{
return true;
}
if(Getpath(root->right,g,path))
{
return true;
}
path.pop();
return false;
}
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
stack<TreeNode*> qpath,ppath;
Getpath(root,p,ppath);
Getpath(root,q,qpath);
while(ppath.size()!=qpath.size())
{
if(ppath.size()>qpath.size())
{
ppath.pop();
}
else
{
qpath.pop();
}
}
while(ppath.top()!=qpath.top())
{
ppath.pop();
qpath.pop();
}
return ppath.top();
}
};
二叉搜索树与双向链表
思路: 该题目要求了空间复杂度,要是不要求的话,直接就中序遍历就好了。将节点prev指向空,cur为4的指针,这里要注意成员函数prev的引用,是必须要带上的,不带会影响整个结构的。将cur以递归的路径进行,prev跟上cur之前的节点。通过cur->left=prev,prev->right=cur。
class Solution {
public:
void InorderConvert(TreeNode* cur,TreeNode*& prev)
{
if(cur==nullptr)
{
return;
}
InorderConvert(cur->left,prev);
cur->left=prev;
if(prev)
{
prev->right=cur;
}
prev=cur;
InorderConvert(cur->right,prev);
}
TreeNode* Convert(TreeNode* pRootOfTree) {
TreeNode* prev=nullptr;
InorderConvert(pRootOfTree,prev);
TreeNode* root=pRootOfTree;
while(root&&root->left)
{
root=root->left;
}
return root;
}
};
从前序与中序遍历序列构造二叉树
思路: 将中序遍历的数组进行划区域处理,ibegin,iend,iroot,中序前序两个数组比较这进行。具体看代码。
class Solution {
public:
TreeNode* _buildTree(vector<int>& preorder, vector<int>& inorder,int& prei,int ibegin,int iend)
{
if(ibegin>iend)
{
return nullptr;
}
TreeNode* root=new TreeNode(preorder[prei]);
int iroot=ibegin;
while(iroot<=iend)
{
if(preorder[prei]==inorder[iroot])
{
break;
}
else
{
iroot++;
}
}
prei++;
root->left= _buildTree(preorder,inorder,prei,ibegin,iroot-1);
root->right= _buildTree(preorder,inorder,prei,iroot+1,iend);
return root;
}
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
int prei=0;
return _buildTree(preorder,inorder,prei,0,preorder.size()-1);
}
};
从中序与后序遍历序列构造二叉树
思路: 该题和上一个题的思路是相同的,就是将前序改为后序了,所以就是prei改为从后开始遍历。
class Solution {
public:
TreeNode* _buildTree(vector<int>& preorder, vector<int>& inorder,int& prei,int ibegin,int iend)
{
if(ibegin>iend)
{
return nullptr;
}
TreeNode* root=new TreeNode(preorder[prei]);
int iroot=ibegin;
while(iroot<=iend)
{
if(preorder[prei]==inorder[iroot])
{
break;
}
else
{
iroot++;
}
}
prei--;
root->right= _buildTree(preorder,inorder,prei,iroot+1,iend);
root->left= _buildTree(preorder,inorder,prei,ibegin,iroot-1);
return root;
}
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
int prei=postorder.size()-1;
return _buildTree(postorder,inorder,prei,0,postorder.size()-1);
}
};
二叉树的前序遍历(非递归)
思路: 创建一个数组和一个找,是将树的左子树先进行都先进入数组按顺序。并且将前面进入数组的节点放入栈当中,之后进行对右子树的遍历,这时要将指向右子树的这颗节点进行删除在栈当中。
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
vector<int> v;
stack<TreeNode*> s;
TreeNode* cur=root;
while(cur || !s.empty())
{
while(cur)
{
v.push_back(cur->val);
s.push(cur);
cur=cur->left;
}
TreeNode* top=s.top();
s.pop();
cur=top->right;
}
return v;
}
};
二叉树的中序遍历(非递归)
思路: 它的思路是和上一道题的解法是相同的,就是将pop出的节点,挨个放入数组。
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> v;
stack<TreeNode*> s;
TreeNode* cur=root;
while(cur || !s.empty())
{
while(cur)
{
s.push(cur);
cur=cur->left;
}
TreeNode* top=s.top();
v.push_back(top->val);
s.pop();
cur=top->right;
}
return v;
}
};
二叉树的后续遍历
思路: 他与上述的问题差距就是如何让右子树在节点的前面输出,而采用的方法就是创建一个变量,用于判断是否右子树已经在父节点前面输出了。
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
vector<int> v;
stack<TreeNode*> s;
TreeNode* cur=root;
TreeNode* pre=nullptr;
while(cur || !s.empty())
{
while(cur)
{
s.push(cur);
cur=cur->left;
}
TreeNode* top=s.top();
if(top->right==nullptr || pre==top->right)
{
v.push_back(top->val);
pre=top;
s.pop();
}
else
{
cur=top->right;
}
}
return v;
}
};