【算法题】 面试级别的二叉树题目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;
    
    }
};

相关推荐
想你依然心痛8 小时前
量子计算对嵌入式密码学的挑战与后量子算法准备
算法·密码学·量子计算
Jerry11 小时前
LeetCode 28. 找出字符串中第一个匹配项的下标
算法
Jerry13 小时前
LeetCode 459. 重复的子字符串
算法
哥不想学算法16 小时前
【C++】字符串字面量拼接
开发语言·c++
海石16 小时前
1500分的题目,确实有实力,不过还是我略胜一筹
算法·leetcode
海石16 小时前
【记忆化搜索】条条大路通AC,走好适合你的那一条,走到后再考虑走得快
算法·leetcode
我叫黑大帅18 小时前
MySQL 并发插入竞态问题:原子写入实践指南
后端·mysql·面试
Jerry18 小时前
LeetCode 151. 反转字符串中的单词
算法
gugucoding19 小时前
31. 【C语言】堆栈与队列的实现
c语言·开发语言·数据结构·链表
我叫黑大帅19 小时前
别再手动写 updated_at了,这坑我踩过
后端·面试·go