目录
层序遍历(一)
思路
代码
    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> arr;
        queue<TreeNode*> q;
        if(root!=nullptr){
            q.push(root);
        }
        while(!q.empty()){
            vector<int> tmp; //存储一层的结点
            int size=q.size(); //此时队列内的元素就是上一层的结点个数
            for(int i=0;i<size;++i){
                tmp.push_back(q.front()->val);
                if(q.front()->left){ //有子树就放进队列中
                    q.push(q.front()->left);
                }
                if(q.front()->right){
                    q.push(q.front()->right);
                }
                q.pop(); //出掉这个父结点
            }
            arr.push_back(tmp);
        }
        return arr;
    } 
 
层序遍历(二)
思路
代码
    vector<vector<int>> levelOrderBottom(TreeNode* root) {
        vector<vector<int>> arr;
        queue<TreeNode*> q;
        if(root!=nullptr){
            q.push(root);
        }
        while(!q.empty()){
            vector<int> tmp;
            int size=q.size();
            for(int i=0;i<size;++i){
                tmp.push_back(q.front()->val);
                if(q.front()->left){
                    q.push(q.front()->left);
                }
                if(q.front()->right){
                    q.push(q.front()->right);
                }
                q.pop();
            }
            arr.push_back(tmp);
        }
        reverse(arr.begin(),arr.end());  //逆置
        return arr;
    } 
根据二叉树创建字符串
思路
代码
    void front_order(TreeNode* root,string& ans){
        if(root==nullptr){
            return ;
        }
        ans+=to_string(root->val);
        if(root->left||root->right){ 
    //左需要特殊判断,左右均有/只有右/只有左,都需要打印左,即使是空括号
            ans+='(';
            front_order(root->left,ans);
            ans+=')';
        }
        if(root->right){ //右只需要在它存在时打印
            ans+="(";
            front_order(root->right,ans);
            ans+=')';
        }
    }
    string tree2str(TreeNode* root) {
        string ans;
        front_order(root,ans);
        return ans;
    } 
二叉树的最近公共祖先
思路
代码
暴力版
    bool find(TreeNode* root, TreeNode* p){
        if(root==nullptr){
            return false;
        }
        if(root==p){
            return true;
        }
        return find(root->left,p)||find(root->right,p); //只要一边找到了就返回真
    }
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if(root==nullptr){
            return nullptr;
        }
        if(root==p||root==q){
            return root;
        }
        //判断当前结点下,要找结点的相对位置
        bool pleft=find(root->left,p);
        bool pright=!pleft;
        bool qleft=find(root->left,q);
        bool qright=!qleft;
        //如果都在左,去左找
        if(pleft&&qleft){
            return lowestCommonAncestor(root->left,p,q);
        }
        //如果都在右,去右找
        else if(pright&&qright){
            return lowestCommonAncestor(root->right,p,q);
        }
        //走到这里,说明一左一右
        else{
            return root;
        }
    } 
队列版
 bool find_q(TreeNode* root, TreeNode* p,queue<TreeNode*>& ans){
        if(root==nullptr){
            return false;
        }
        if(root==p){ 
            ans.push(root); //队列:先入子结点,保证先出的是子结点
            return true;
        }
        if(find_q(root->left,p,ans)){ //为真就存储起来(说明当前结点是路径上的一点)
            ans.push(root);
            return true;
        }
        if(find_q(root->right,p,ans)){ //同理
            ans.push(root);
            return true;
        } 
        return false; //走到这里,说明左右均没找到,就说明这条路没有要找的结点
    } 
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        queue<TreeNode*> sp,sq;
        find_q(root,p,sp);
        find_q(root,q,sq);
        //先将多的出掉
        while(sp.size()>sq.size()){
            sp.pop();
        }
        while(sp.size()<sq.size()){
            sq.pop();
        }
        //然后同时出,直到找到那个公共结点
        while(sp.front()!=sq.front()){
            sp.pop();
            sq.pop();
        }
        return sp.front();
    } 
栈版
    bool find_s(TreeNode* root, TreeNode* p,stack<TreeNode*>& ans){
        if(root==nullptr){
            return false;
        }
        ans.push(root); //注意:栈必须得先入父结点,保证先出的是子结点
        if(root==p){
            return true;
        }
        if(find_s(root->left,p,ans)){
            return true;
        }
        if(find_s(root->right,p,ans)){
            return true;
        }
        ans.pop();
        return false;
    }
    
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        stack<TreeNode*> sp,sq;
        find_s(root,p,sp);
        find_s(root,q,sq);
        while(sp.size()>sq.size()){
            sp.pop();
        }
        while(sp.size()<sq.size()){
            sq.pop();
        }
        while(sp.top()!=sq.top()){
            sp.pop();
            sq.pop();
        }
    } 
bs树和双向链表
思路
代码
	void inorder(TreeNode* root,TreeNode*& prev){
		if(root==nullptr){
			return;
		}
		inorder(root->left,prev);
		root->left=prev;
		if(prev){ //prev会为空,所以需要判断,不然就越界了
			prev->right=root;
		}
		prev=root; //因为之后要进root的后继结点了,所以需要更新prev
		inorder(root->right,prev);
	}
    TreeNode* Convert(TreeNode* pRootOfTree) {
		if(pRootOfTree==nullptr){
			return nullptr;
		}
		TreeNode *prev=nullptr,*tmp=pRootOfTree;
		while(tmp->left!=nullptr){ //拿到链表的第一个结点
			tmp=tmp->left;
		}
		inorder(pRootOfTree,prev);
		return tmp;
    } 
前序中序序列构建二叉树
思路
代码
class Solution {
public:
    TreeNode* _build(vector<int>& preorder, vector<int>& inorder, int& prei, int inbegin, int inend) {
        if (inbegin > inend) { //数组不合法,说明不存在这个结点,所以返回空
            return nullptr;
        }
        TreeNode* node = new TreeNode(preorder[prei]); //按照前序构建二叉树(因为先拿到的都是根结点)
        int begin = inbegin;
        // while(preorder[prei]!=inorder[begin]&&begin<=inend){
        //     begin++;
        // }
        for (; begin <= inend; ++begin) { //在中序中找到根结点
            if (preorder[prei] == inorder[begin]) {
                break;
            }
        }
        ++prei; //拿到下一个结点
        node->left = _build(preorder, inorder, prei, inbegin, begin - 1);//在找到的根结点,左区间是左子树
        node->right = _build(preorder, inorder, prei, begin + 1, inend);//同理
        return node;//左右子树构建完毕后,返回该结点
    }
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        int prei = 0, inbegin = 0, inend = inorder.size();
        TreeNode* root = _build(preorder, inorder, prei, 0, (int)inorder.size() - 1);
        //注意这里的prei是引用
        return root; //最后返回的就是根结点
    }
}; 
中序后序序列构建二叉树
思路
代码
TreeNode* _build(vector<int>& inorder, vector<int>& postorder,int& posti,int inbegin,int inend){
        if(inbegin>inend){
            return nullptr;
        }
        TreeNode* root=new TreeNode(postorder[posti]);
        int begin=inbegin;
        while(begin<=inend){
            if(postorder[posti]==inorder[begin]){
                break;
            }
            begin++;
        }
        --posti;  //注意是--嗷
        root->right=_build(inorder,postorder,posti,begin+1,inend);//先被构建的是右子树
        root->left=_build(inorder,postorder,posti,inbegin,begin-1);
        return root;
}
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        int posti=postorder.size()-1;
        TreeNode* root=_build(inorder,postorder,posti,0,inorder.size()-1);
        return  root;
    } 
非递归前序遍历
思路
代码
vector<int> preorderTraversal(TreeNode* root) {
        vector<int> ans;  //存放前序序列的结点值
        stack<TreeNode*> tmp; //存放左结点指针,用于访问其右子树
        TreeNode* cur=root;
        while(!tmp.empty()||cur){ //栈空+当前结点是空结点,出循环
            while(cur){
                ans.push_back(cur->val); //入左结点
                tmp.push(cur); //存左结点指针
                cur=cur->left;
            }
            TreeNode* top=tmp.top(); 
            cur=top->right; //访问右子树
            tmp.pop();
        }
        return ans;
    } 
非递归中序遍历
思路
代码
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> ans;  //存放中序序列的结点值
        stack<TreeNode*> tmp; //存放左结点指针,用于访问其右子树
        TreeNode* cur=root;
        while(!tmp.empty()||cur){ //栈空+当前结点是空结点,出循环
            while(cur){ //把所有左结点入栈
                tmp.push(cur);
                cur=cur->left;
            }
            cur=tmp.top();  //拿取栈顶元素
            ans.push_back(cur->val); //入中序序列
            cur=cur->right; //访问其右子树
            tmp.pop(); //该结点没啥用了,直接出
        }
        return ans;
    } 
非递归后序遍历
思路
代码
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> ans;  //存放中序序列的结点值
        stack<TreeNode*> tmp; //存放左结点指针,用于访问其右子树
        TreeNode* cur=root,*prev=nullptr; 
        while(!tmp.empty()||cur){ //栈空+当前结点是空结点,出循环
            while(cur){ //把所有左结点入栈(cur就用于把当前结点的左结点存入栈)
                tmp.push(cur);              
                cur=cur->left;
            }
            TreeNode* top=tmp.top(); //代表当前的根结点
            if(top->right==nullptr || top->right==prev){
                ans.push_back(top->val); //入后序序列
                prev=top; //用于下一次循环时,判断上一个结点的右子树是否被访问过
                tmp.pop(); //该结点没啥用了,直接出
            }
            else{
                cur=top->right; //没有被访问过,就去右子树进行循环
            }
        }
        return ans;
    }









