leetcode200题之二叉树专题(二)

1. 二叉树的前序、中序、后序遍历

(1)递归解决:根据前序遍历根左右,中序遍历左根右,后序遍历左右根即可。

class Solution {
public:
    vector<int> res;
    vector<int> preorderTraversal(TreeNode* root) {
        if(root==nullptr) return {};
        recur(root);
        return res;
    }
    void recur(TreeNode* root){
        if(root==nullptr) return;
        //1.前序遍历
        res.push_back(root->val);
        recur(root->left);
        recur(root->right);

        //2.中序遍历
        recur(root->left);
        res.push_back(root->val);
        recur(root->right);

        //3.后序遍历
        res.push_back(root->val);
        recur(root->right);
        recur(root->left);
    }
};

(2) 迭代实现

class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> res;
        if(root==nullptr) return {};
        stack<TreeNode*> s;
        s.push(root);
        while(!s.empty()){
            TreeNode* cur=s.top();
            s.pop();
            if(cur!=nullptr){
                if(cur->right)  s.push(cur->right);
                if(cur->left)  s.push(cur->left);
                s.push(cur);         // 前序:栈结构-“先进后出”,所以根最后进先出
                s.push(nullptr);     //标记访问过
                
                //中序遍历
                if(cur->right)  s.push(cur->right);
                s.push(cur);         // 中序:栈结构-“先进后出”,push顺序为右根左
                s.push(nullptr);     //标记访问过
                if(cur->left)  s.push(cur->left);

                //后序遍历
                s.push(cur);         // 后序:栈结构-“先进后出”,push顺序为根右左
                s.push(nullptr);     //标记访问过
                if(cur->right)  s.push(cur->right);
                if(cur->left)  s.push(cur->left);
            }
            else{
                res.push_back(s.top()->val); //前面s.pop()已经去掉nullptr,
                                             //所以s.top()得到的是下面的值。
                s.pop();
            }
        }
        return res;
    }
};

2. 从前序和中序遍历序列构造二叉树、从中序和后序遍历序列构造二叉树

原理:

前序遍历:根-左-右

中序遍历:左-根-右

可以根据前序遍历得到根节点,然后在中序遍历中找到根节点的位置,可得左子树的节点数和右子树的节点数。递归即可。

代码

class Solution {
public:
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        return build(preorder,0,preorder.size()-1,inorder,0, inorder.size()-1);
    }
    TreeNode* build(vector<int>& preorder,int l1, int r1, vector<int>& inorder,int l2,int r2){
        //前+中-->构造二叉树
        if(l1>r1)  return nullptr;
        TreeNode* root=new TreeNode(preorder[l1]);
        int k=l2;
        while(k<=r2 && inorder[k]!=root->val) k++;
        int left_len=k-l2;
        root->left =build(preorder,l1+1,l1+left_len, inorder,l2,k-1);
        root->right=build(preorder,l1+left_len+1,r1, inorder,k+1,r2);
        return root;

        //中+后-->构造二叉树
        if(l1>r1) return nullptr;
        TreeNode* root = new TreeNode(postorder[r2]);
        int k=l1;
        while(k<r1 && inorder[k]!= root->val) k++;
        int left_len=k-l1;
        root->left=build(inorder,l1,k-1,postorder,l2,l2+left_len-1);
        root->right=build(inorder,k+1,r1,postorder,l2+left_len,r2-1);
        return root;
    }
};

3. 二叉树的层序遍历

利用队列: push左,push右;   循环结束条件:q.empty()

class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> res;
        if(root==nullptr)  return{};
        queue<TreeNode*> q;
        q.push(root);
        while(!q.empty()){
            vector<int> tmp;
            for(int i=q.size(); i>0; i--){
                TreeNode* cur=q.front();
                q.pop();
                tmp.push_back(cur->val);
                if(cur->left) q.push(cur->left);
                if(cur->right) q.push(cur->right);
            }
            res.push_back(tmp);
        }
        return res;
    }
};

4. 二叉树的“之”字形遍历

    用deque: 头部出,尾部加;  设置flag:用来改变不同层内部的实现;   循环结束条件:dq.empty();

class Solution {
public:
    vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
        vector<vector<int>> res;
        deque<TreeNode*> dq;
        if(root==nullptr)  return res;
        dq.push_back(root);
        bool flag=true;
        while(!dq.empty()){
            vector<int> tmp;
            for(int i=dq.size();i>0;i--){
                //奇数层
                if(flag){
                    TreeNode* node=dq.back();
                    dq.pop_back();
                    tmp.push_back(node->val);
                    if(node->left!=nullptr)  dq.push_front(node->left);
                    if(node->right!=nullptr) dq.push_front(node->right);
                }
                //偶数层
                else{
                    TreeNode* node=dq.front();
                    dq.pop_front();
                    tmp.push_back(node->val);
                    if(node->right!=nullptr) dq.push_back(node->right);
                    if(node->left!=nullptr)  dq.push_back(node->left);
                }
            }
            res.push_back(tmp);
            flag=!flag;
        }
        return res;
    }
};

5. 二叉树的右视图

class Solution {
public:
    vector<int> rightSideView(TreeNode* root) {
        vector<int> res;
        queue<TreeNode*> q;
        if(root==nullptr)  return res;
        q.push(root);
        while(!q.empty()){
            TreeNode* node;
            for(int k=q.size(); k>0; k--){
                node=q.front();
                q.pop();
                if(node->left!=nullptr)  q.push(node->left);
                if(node->right!=nullptr) q.push(node->right);
            }
            res.push_back(node->val);  //将每层的最右边的值push_back
        }
        return res;
    }
};

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值