移情别恋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;
    }
};
相关推荐
浮生如梦_35 分钟前
Halcon基于laws纹理特征的SVM分类
图像处理·人工智能·算法·支持向量机·计算机视觉·分类·视觉检测
XiaoLeisj2 小时前
【JavaEE初阶 — 多线程】单例模式 & 指令重排序问题
java·开发语言·java-ee
励志成为嵌入式工程师2 小时前
c语言简单编程练习9
c语言·开发语言·算法·vim
捕鲸叉3 小时前
创建线程时传递参数给线程
开发语言·c++·算法
A charmer3 小时前
【C++】vector 类深度解析:探索动态数组的奥秘
开发语言·c++·算法
Peter_chq3 小时前
【操作系统】基于环形队列的生产消费模型
linux·c语言·开发语言·c++·后端
wheeldown4 小时前
【数据结构】选择排序
数据结构·算法·排序算法
记录成长java5 小时前
ServletContext,Cookie,HttpSession的使用
java·开发语言·servlet
前端青山5 小时前
Node.js-增强 API 安全性和性能优化
开发语言·前端·javascript·性能优化·前端框架·node.js
青花瓷5 小时前
C++__XCode工程中Debug版本库向Release版本库的切换
c++·xcode