移情别恋c++ ദ്ദി˶ー̀֊ー́ ) ——12.二叉树(习题)

1.根据二叉树创建字符串

. - 力扣(LeetCode)

我的思路:

  1. 根节点单独讨论,因为,根节点之后才会开始有括号

2.根节点的左孩子和右孩子分别进入operation函数

operation函数:

1.如果root不为空,先加(,再加root->val

2.分类讨论:

1.if(root->left==NULL&&root->right==NULL)

如果为叶子节点:直接加)

2.if(root->left==NULL&&root->right!=NULL)

如果左为空,右不为空;

无法省略括号,需要加()

3.如果左右都不为空

递归

operation(root->left,arr);

operation(root->right,arr);

最后加)

函数介绍**:to_string,可将整形转换为string;**

class Solution {
public:
     void operation(TreeNode* root,string& arr)
     {
        if(root)
        {
          arr.push_back('(');
          arr+=to_string(root->val);
          if(root->left==NULL&&root->right==NULL)
          {
             arr.push_back(')');
          }
          else
          {
             if(root->left==NULL&&root->right!=NULL)
             {
                arr.push_back('(');
                arr.push_back(')');
             }
              
              operation(root->left,arr);
              operation(root->right,arr);
              arr.push_back(')');
          }
        }
     }

    string tree2str(TreeNode* root) {
     string arr;
     if(root)
     {
        arr+=to_string(root->val);
        if(root->left==NULL&&root->right!=NULL)
        {
                arr.push_back('(');
                arr.push_back(')');
        }
        operation(root->left,arr);
        operation(root->right,arr);
     }
     return arr;
    }
};

2.二叉树的分层遍历1

. - 力扣(LeetCode)

我的思路:

  1. 建一个栈,并把根节点入栈,记录栈的大小;

2.while(size)

出栈,size--,并将左右节点入栈

3.size=栈的size;

4.若栈为空,则已经遍历完毕;

class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
     TreeNode* tmp;
     vector<int> brr;
     vector<vector<int>> arr;
     queue<TreeNode*> it;
     int size=0;
     if(root!=NULL)
     {
       it.push(root);
       size++;
     }
      while(it.size())
      {
        while(size)
        {
          tmp=it.front();
          brr.push_back(tmp->val);
          it.pop();
          size--;
          if(tmp->left)
          {
            it.push(tmp->left);
          }

          if(tmp->right)
          {
            it.push(tmp->right);
          }
        }
        arr.push_back(brr);
        brr.clear();
        size=it.size();
      }

      return arr;

    }
};

3.二叉树的分层遍历2

. - 力扣(LeetCode)

和前一题一样,只需在最后reverse(arr.begin(),arr.end());

class Solution {
public:
    vector<vector<int>> levelOrderBottom(TreeNode* root) {
     TreeNode* tmp;
     vector<int> brr;
     vector<vector<int>> arr;
     queue<TreeNode*> it;
     int size=0;
     if(root!=NULL)
     {
       it.push(root);
       size++;
     }
      while(it.size())
      {
        while(size)
        {
          tmp=it.front();
          brr.push_back(tmp->val);
          it.pop();
          size--;
          if(tmp->left)
          {
            it.push(tmp->left);
          }

          if(tmp->right)
          {
            it.push(tmp->right);
          }
        }
        arr.push_back(brr);
        brr.clear();
        size=it.size();
      }
      reverse(arr.begin(),arr.end());
      return arr;
    }
};

4.最近公共祖先

. - 力扣(LeetCode)

我的思路:

1.先写一个查找函数

2.从根节点开始查找p

  1. 再从p开始查找q
    如果找到了,返回p

如果没找到,那么p就变成p的父节点,再继续查找,直至从p可以找到q,返回p

class Solution {
public:
      bool qfirstfind(TreeNode* p, TreeNode* q)
      {
        if(p==nullptr)
        return false;
        else if(p!=q)
        {
            if(qfirstfind(p->left, q))
            return true;
            else
            return qfirstfind(p->right, q);
        }
        else if(p==q)
        return true;
        
        return 1;
      }                          //这个函数用来查找p之下是否有q
       

       void firstfind(TreeNode* p, TreeNode* q,TreeNode*&parent)
      {
        if(p!=nullptr)
        {
            if(p->left!=q&&p->right!=q)
            {
               firstfind(p->left, q,parent);
               firstfind(p->right, q,parent);
            }
        else
        {
            parent=p;            //这里用来保存q的父节点
        }
        }
      }

       void secondfind(TreeNode* root, TreeNode*&p, TreeNode*&q)
       {
            TreeNode* it;
            while((p->left!=q)&&(p->right!=q)&&(p!=root))
            {
                firstfind(root,p,it);
                p=it;           //p赋值为其父节点
                if(qfirstfind(p,q))
                {
                    break;
                }
            }
       }

    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        {
            if(qfirstfind(p,q))
            return p;
            if(qfirstfind(q,p))
            return q;                    //如果p,q有一个是公共祖先,则直接返回
            secondfind(root, p, q);
            return p;
    
        }
    }
};

更好的的思路 !!!!!!!!:

用两个栈分别存放****从根找到p,q的路径

1.若两个栈大小不一致

则用pop函数,保证二者大小一致

2.若两栈的top不一致,则二者都pop

直至两者的top相同,返回二者的top,即为最近的公共祖先

class Solution {
public:
     bool findpath(TreeNode* root, TreeNode* x,stack<TreeNode*>&path)
     {
        if(root==nullptr)
        return false;

        path.push(root);     

        if(root==x)
        return true;
        
        if(findpath(root->left,x,path))
        return true;

        if(findpath(root->right,x,path))
        return true;

        path.pop();     //走到这一步,证明root的左右子树都没有x,所以要把root删除
        return false;
     }





    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        stack<TreeNode*> ppath,qpath;
        findpath(root,p,ppath);
        findpath(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();
    }
};

5.二叉树搜索树转换成排序双向链表

二叉搜索树与双向链表_牛客题霸_牛客网

我的思路:

1.find1函数:寻找左子树中的最大值

2.find2函数:寻找右子树中的最小值

3.find3函数:寻找头节点,即二叉树中的最小值

从叶子节点开始连接

class Solution {
public:
    
	void creat(TreeNode*root)
	{
		if(root!=nullptr)
         {
			if(root->left==nullptr&&root->right==nullptr)
		 {
			return;
		 }
          else{

             TreeNode*qleft=root->left;
             TreeNode*qright=root->right;
            creat(qleft);
			creat(qright);

             TreeNode*nleft=find1(root);
             TreeNode*nright=find2(root);
			 if(nleft)
		     nleft->right=root;
			 if(nright)
		     nright->left=root;
		     root->left=nleft;
		     root->right=nright;

			
		  }
		 }
	}


 TreeNode*find1(TreeNode*root)
 {
	 TreeNode*it = root->left;  
	 if(it)            //左右都不为空,找左子树最大的
    {
		while (it->right)
      {
	  it = it->right;
      }
	  return it;
	}
	else {
	return nullptr;
	}
 }

TreeNode*find2(TreeNode*root)
 {
	 TreeNode*it = root->right;  //左右都不为空,找右子树最小的
	 if(it)
      {
		while (it->left)
       {
	     it = it->left;
       }
	return it;
	  }
	  else {
	  return nullptr;
	  }
 }

TreeNode*find3(TreeNode*root)
 {            //找根
    TreeNode* it=root;
    while (it->left)
    {
	  it = it->left;
    }
	return it;
 }
    TreeNode* Convert(TreeNode* pRootOfTree) {

        if(pRootOfTree==nullptr)
		return pRootOfTree;

		TreeNode*head=find3(pRootOfTree);
        creat(pRootOfTree);
        return head;
    }
};

6.前序中序还原二叉树

. - 力扣(LeetCode)

思路:

1.preorder 确定根

2.确定根了之后,将inorder分成两部分,左边为左子树,右边为右子树

3.分别递归左边和右边

class Solution {
public:
    TreeNode* creat(vector<int>& preorder, vector<int>& inorder,int &prev,int begin,int end)
    {
        TreeNode* root;
        if(begin>end)
        return nullptr;
        int flag=preorder[prev];
        int i=0;
       while(flag!=inorder[i])
       {
         i++;
       }
        root=new TreeNode(flag);
        prev++;
       root->left=creat(preorder,inorder,prev,begin,i-1);  //前序遍历,根左右,根后是左子树,所以先构建左子树
       root->right=creat(preorder,inorder,prev,i+1,end);   //有点类似并归排序
       return root;
    }


    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
    TreeNode* root;
    int prev=0;     //前序遍历,从头开始找根
    root=creat(preorder,inorder,prev,0,preorder.size()-1);
    return root;
    }
};

7.中序和后序还原二叉树

. - 力扣(LeetCode)

和上一题一样,中序确定左右子树

但不同的是得从后序遍历的尾开始找根,且根前是右子树

class Solution {
public:
 TreeNode* creat(vector<int>& postorder, vector<int>& inorder,int &prev,int begin,int end)
    {
        TreeNode* root;
        if(begin>end)
        return nullptr;
        int flag=postorder[prev];
        int i=0;
       while(flag!=inorder[i])
       {
         i++;
       }
        root=new TreeNode(flag);
        prev--;
       root->right=creat(postorder,inorder,prev,i+1,end);   //后序遍历左右根,倒着找的话,根的前面是右子树,所以右子树先建立
       root->left=creat(postorder,inorder,prev,begin,i-1);
       return root;
    }
    

    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
    TreeNode* root;
    int prev=inorder.size()-1;   //从尾开始找根
    root=creat(postorder,inorder,prev,0,inorder.size()-1);
    return root;
    }
};
相关推荐
zwjapple1 分钟前
typescript里面正则的使用
开发语言·javascript·正则表达式
小五Five3 分钟前
TypeScript项目中Axios的封装
开发语言·前端·javascript
前端每日三省4 分钟前
面试题-TS(八):什么是装饰器(decorators)?如何在 TypeScript 中使用它们?
开发语言·前端·javascript
凡人的AI工具箱18 分钟前
15分钟学 Go 第 60 天 :综合项目展示 - 构建微服务电商平台(完整示例25000字)
开发语言·后端·微服务·架构·golang
做人不要太理性21 分钟前
【C++】深入哈希表核心:从改造到封装,解锁 unordered_set 与 unordered_map 的终极奥义!
c++·哈希算法·散列表·unordered_map·unordered_set
程序员-King.30 分钟前
2、桥接模式
c++·桥接模式
chnming198734 分钟前
STL关联式容器之map
开发语言·c++
进击的六角龙35 分钟前
深入浅出:使用Python调用API实现智能天气预报
开发语言·python
檀越剑指大厂35 分钟前
【Python系列】浅析 Python 中的字典更新与应用场景
开发语言·python
VertexGeek36 分钟前
Rust学习(八):异常处理和宏编程:
学习·算法·rust