【算法题】 面试级别的二叉树题目OJ复习(下)


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

105. 从前序与中序遍历序列构造二叉树https://leetcode.cn/problems/construct-binary-tree-from-preorder-and-inorder-traversal/

给定两个整数数组 preorderinorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。

写法一:递归

cpp 复制代码
class Solution {
public:
    TreeNode* build(vector<int>& preorder, vector<int>& inorder,int& prev,int inbegin,int inend)
    {
        if(inbegin>inend)
        return nullptr;
        //前序确定根
        TreeNode* root=new TreeNode(preorder[prev]);
        //中序分割
        int rooti=inbegin;
        while(preorder[prev]!=inorder[rooti])
        rooti++;

        prev++;
        root->left =build(preorder,inorder,prev,inbegin,rooti-1);
        root->right=build(preorder,inorder,prev,rooti+1,inend);
        return root;

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

写法二:哈希表

cpp 复制代码
class Solution {
public:
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        int n = preorder.size();
        unordered_map<int, int> index;
        for (int i = 0; i < n; i++) {
            index[inorder[i]] = i;
        }

        auto dfs = [&](this auto&& dfs, int pre_l, int pre_r, int in_l) -> TreeNode* {
            if (pre_l == pre_r) { // 空节点
                return nullptr;
            }
            int left_size = index[preorder[pre_l]] - in_l; // 左子树的大小
            TreeNode* left = dfs(pre_l + 1, pre_l + 1 + left_size, in_l);
            TreeNode* right = dfs(pre_l + 1 + left_size, pre_r, in_l + 1 + left_size);
            return new TreeNode(preorder[pre_l], left, right);
        };
        return dfs(0, n, 0); // 左闭右开区间
    }
};

从中序与后序遍历序列构造二叉树

106. 从中序与后序遍历序列构造二叉树https://leetcode.cn/problems/construct-binary-tree-from-inorder-and-postorder-traversal/

给定两个整数数组 inorderpostorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树

cpp 复制代码
class Solution {
public:
    TreeNode* build(vector<int>& inorder, vector<int>& postorder,int& prev,int inbegin,int inend)
    {
    
        if(inbegin>inend)
        return nullptr;
        //后序确定根
        TreeNode* root=new TreeNode(postorder[prev]);
        //中序分割
        int rooti=inbegin;
        while(inorder[rooti]!=postorder[prev])
        {
            rooti++;
            if(rooti==inorder.size())
            break;
        }
        
        if(prev==0)
        return root;
        prev--;
        
        root->right=build(inorder,postorder,prev,rooti+1,inend);
        root->left=build(inorder,postorder,prev,inbegin,rooti-1);
        
        return root;
    }
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder)
     {
        int i=postorder.size()-1;
        return build(inorder,postorder,i,0,inorder.size()-1);
    }
};

二叉树的前序遍历

144. 二叉树的前序遍历https://leetcode.cn/problems/binary-tree-preorder-traversal/

给你二叉树的根节点 root ,返回它节点值的 前序遍历。

方法一:迭代

cpp 复制代码
class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        stack<TreeNode*> st;
        TreeNode* rooti=root;
        vector<int> vv;
        
        while(rooti||!st.empty())
        {
            while(rooti)
            {
                vv.push_back(rooti->val);
                st.push(rooti);
                rooti=rooti->left;
            }
            TreeNode* top=st.top();
            rooti=top->right;
            st.pop();
        }
        return vv;
    }
};

方法二:Morris 遍历

cpp 复制代码
class Solution {
public:
    vector<int> preorderTraversal(TreeNode *root) {
        vector<int> res;
        if (root == nullptr) {
            return res;
        }

        TreeNode *p1 = root, *p2 = nullptr;

        while (p1 != nullptr) {
            p2 = p1->left;
            if (p2 != nullptr) {
                while (p2->right != nullptr && p2->right != p1) {
                    p2 = p2->right;
                }
                if (p2->right == nullptr) {
                    res.emplace_back(p1->val);
                    p2->right = p1;
                    p1 = p1->left;
                    continue;
                } else {
                    p2->right = nullptr;
                }
            } else {
                res.emplace_back(p1->val);
            }
            p1 = p1->right;
        }
        return res;
    }
};

二叉树的中序遍历

94. 二叉树的中序遍历https://leetcode.cn/problems/binary-tree-inorder-traversal/

给定一个二叉树的根节点 root ,返回 它的 中序 遍历

cpp 复制代码
class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        TreeNode* rooti=root;
        stack<TreeNode*> st;
        vector<int> vv;
        
        while(rooti||!st.empty())
        {
            while(rooti)
            {
                st.push(rooti);
                rooti=rooti->left;
            }
            TreeNode* top=st.top();
            vv.push_back(top->val);
            st.pop();
            rooti=top->right;
        }
        return vv;
    }
};

二叉树的后序遍历

145. 二叉树的后序遍历https://leetcode.cn/problems/binary-tree-postorder-traversal/

给你一棵二叉树的根节点 root ,返回其节点值的 后序遍历 。

cpp 复制代码
class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
    
        TreeNode* rooti=root;
        TreeNode* prev=nullptr;
        stack<TreeNode*> st;
        vector<int> vv;
        
        while(rooti||!st.empty())
        {
            while(rooti)
            {
                st.push(rooti);
                rooti=rooti->left;
            }
            TreeNode* top=st.top();
            
            if(top->right&&prev!=top->right)
            {
                rooti=top->right;
            }
            else
            {
                vv.push_back(top->val);
                st.pop();
                prev=top;
            }
        }
        return vv;
    
    }
};

相关推荐
Darling噜啦啦12 小时前
列表转树算法深度解析:从 Map 到 Reduce 的两种实现,面试高频考点
数据结构·算法·面试
swipe13 小时前
正则表达式入门到进阶:从表单校验到手写模板引擎
前端·javascript·面试
神奇小汤圆14 小时前
RAG大厂面试题汇总:向量检索、混合检索、Rerank、幻觉处理高频问题
面试
clint45614 小时前
C++进阶(1)——前景提要
c++
用户4978630507316 小时前
(一)小红的数组操作
算法·编程语言
假如让我当三天老蒯16 小时前
回归基本功:Map/Set 与 WeakMap/WeakSet 的区别
前端·面试
夜悊18 小时前
C++代码示例:进制数简单生成工具
c++
怕浪猫18 小时前
Electron 系列文章封面图
算法·架构·前端框架
郝学胜_神的一滴20 小时前
CMake 021: IF 条件判据详诠
c++·cmake
假如让我当三天老蒯20 小时前
回归基本功!前端的解构赋值、扩展运算符、剩余参数
前端·面试