二叉树常见OJ题(笔记)

目录

 前言

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

2. 二叉树的层序遍历

3. 二叉树的层序遍历 II

4. 二叉树的最近公共祖先

5.二叉搜索树与双向链表

6.从前序与中序遍历序列构造二叉树

7. 二叉树的前序遍历非递归

8. 二叉树的中序遍历非递归

9. 二叉树的后序遍历非递归


 前言

本篇总结了常见二叉树算法题,每个标题都有超链接,并给出AC代码。记得以后再刷几遍,容易忘记。

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

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
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. 二叉树的层序遍历

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
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(size_t 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);
            //当前层出完了,下一层都进队列,队列的size就是下一层的数据个数
            levelSize=q.size();
        }
        return vv;
    }
};

3. 二叉树的层序遍历 II

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<vector<int>> levelOrderBottom(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(size_t 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);
            //当前层出完了,下一层都进队列,队列的size就是下一层的数据个数
            levelSize=q.size();
        }
        reverse(vv.begin(),vv.end());
        return vv;
    }
};


4. 二叉树的最近公共祖先

方法一:O(H*N)

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    bool Find(TreeNode* sub,TreeNode* x)
    {
        if(sub==nullptr)
            return false;
        return sub == x
            ||Find(sub->left,x)
            ||Find(sub->right,x);
    }
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) 
    {
        if(root==nullptr)
            return nullptr;
        
        if(root == p || root == q)
            return root;
        
        bool pInLeft,pInRight,qInLeft,qInRight;
        pInLeft = Find(root->left,p);
        pInRight = !pInLeft;

        qInLeft = Find(root->left,q);
        qInRight = !qInLeft;

        //1、一个在左一个在右,root就是最近公共祖先
        //2、都在左,递归去左子树找
        //3、都在右,递归去右子树找
        if((pInLeft&&qInRight)||(qInLeft&&pInRight))
        {
            return root;
        }
        else if(pInLeft&&qInLeft)
        {
            return lowestCommonAncestor(root->left,p,q);
        }
        else if(pInRight&&qInRight)
        {
            return lowestCommonAncestor(root->right,p,q);
        }
        else
        {
            //理论上不会走到这里
            return nullptr;
        }
    }
};

方法二:O(N)

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
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();
        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.二叉搜索树与双向链表

/*
struct TreeNode {
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
	TreeNode(int x) :
			val(x), left(NULL), right(NULL) {
	}
};*/
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* head = pRootOfTree;
		while(head&&head->left)
		{
			head=head->left;
		}
		return head;
    }
};

6.从前序与中序遍历序列构造二叉树

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    TreeNode* _buildTree(vector<int>&preorder,vector<int>&inorder,int& prei,int inbegin, int inend)
    {
        if(inbegin>inend)
            return nullptr;
        
        TreeNode* root = new TreeNode(preorder[prei++]);
        //分割中序
        int ini=inbegin;
        while(ini <= inend)
        {
            if(inorder[ini] == root->val)
                break;
            else
                ++ini;
        }

        //[inbegin,ini-1] ini [ini+1,inend]
        root->left = _buildTree(preorder,inorder,prei,inbegin,ini-1);
        root->right = _buildTree(preorder,inorder,prei,ini+1,inend);

        return root;
    }
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        int i=0;
        return _buildTree(preorder,inorder,i,0,inorder.size()-1);
    }
};

7. 二叉树的前序遍历非递归

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
 //法一
class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> result;
        stack<TreeNode*> st;
        if(root==nullptr)return result;
        st.push(root);
        TreeNode* cur=nullptr;
        while(!st.empty())
        {
            cur=st.top();
            st.pop();
            result.push_back(cur->val);
            if(cur->right)st.push(cur->right);
            if(cur->left)st.push(cur->left);

        }
        
        return result;
    }
};
//法二
class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        stack<TreeNode*> st;
        vector<int> v;
        TreeNode* cur = root;
        while(cur || !st.empty())
        {
            //开始访问一棵树
            //1、左路节点
            while(cur)
            {
                v.push_back(cur->val);
                st.push(cur);

                cur = cur->left;
            }
            // 2、左路节点的右子树需要访问
            TreeNode*top = st.top();
            st.pop();

            cur = top->right;
        }

        return v;
    }
};

8. 二叉树的中序遍历非递归

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
 //法一
class Solution {
public:

    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> result;
        stack<TreeNode*> st;
        TreeNode*cur=root;
        while(cur!=nullptr||!st.empty())
        {
            if(cur!=nullptr)
            {
                st.push(cur);
                cur=cur->left;
            }
            else
            {
                cur=st.top();
                result.push_back(cur->val);
                st.pop();
                cur=cur->right;
            }
        }
        return result;
    }
};
//法二
class Solution {
public:

    vector<int> inorderTraversal(TreeNode* root) {
        stack<TreeNode*> st;
        vector<int> v;
        TreeNode* cur = root;
        while(cur || !st.empty())
        {
            //开始访问一棵树
            //1、左路节点入栈
            while(cur)
            {
                st.push(cur);
                cur = cur->left;
            }
            // 2、当左路节点从栈中出来,表示左子树已经访问过了,应该访问这个节点和它的右节点
            TreeNode*top = st.top();
            st.pop();
            v.push_back(top->val);
            cur = top->right;
        }

        return v;
    }
};

9. 二叉树的后序遍历非递归

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
 //法一
class Solution {
public:

    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> result;
        stack<TreeNode*> st;
        if(root==NULL)return result;
        TreeNode*cur=NULL;
        TreeNode*pre=NULL;
        st.push(root);
        while(!st.empty())
        {
            cur=st.top();
            if((cur->left==NULL&&cur->right==NULL)||
            (pre!=NULL&&(pre==cur->left||pre==cur->right)))
            {
                result.push_back(cur->val);
                st.pop();
                pre=cur;
            }
            else
            {
                if(cur->right!=NULL)st.push(cur->right);
                if(cur->left!=NULL)st.push(cur->left);
            }
        }

        return result;
    }
};
//法二
class Solution {
public:

    vector<int> postorderTraversal(TreeNode* root) {
        stack<TreeNode*> st;
        vector<int> v;
        TreeNode* cur = root;
        TreeNode* prev = nullptr;
        while(cur || !st.empty())
        {
            //开始访问一棵树
            //1、左路节点入栈
            while(cur)
            {
                st.push(cur);
                cur = cur->left;
            }
            // 2、当左路节点从栈中出来,表示左子树已经访问过了
            TreeNode*top = st.top();

            //栈顶节点右子树为空或者上一个访问节点是右子树的根,说明右子树已经访问过了,可以访问上一个节点的右数
            //否则 子问题访问top的右子树
            if(top->right == nullptr||top->right == prev)
            {
                v.push_back(top->val);
                prev = top;
                cur = nullptr;
                st.pop();
            }
            else{
                cur = top->right;//子问题访问右子树
            }
        }

        return v;
    }
};

猜你喜欢

转载自blog.csdn.net/m0_67759533/article/details/131584557