剑指offer-31--34二叉树OJ题(C++)

二叉树OJ题

  • I. 从上到下打印二叉树
  • 2.从上到下打印二叉树 II
  • 3.从上到下打印二叉树 III
  • 4.二叉搜索树的后序遍历序列

I. 从上到下打印二叉树

题目链接:https://leetcode-cn.com/problems/cong-shang-dao-xia-da-yin-er-cha-shu-lcof/

剑指offer-31--34二叉树OJ题(C++)_第1张图片

这道题考察二叉树的层序遍历,也就是广度优先搜索(BFS),BFS通常借助队列先进先出的特点

基本步骤:

  • 特例处理:树的根节点为空时,直接返回空列表
  • 将根节点入队,打印结果列表ans
  • BFS循环处理:当队列为空时结束循环
    1.出队:搞一个指针(tmp)指向队首元素。队首元素出队
    2.打印:将val添加至ans
    3.添加子节点:若tmp指向的结点的左右子节点不为空,则将左右子节点入队

动图演示:

剑指offer-31--34二叉树OJ题(C++)_第2张图片

代码如下:

class Solution {
    private:
        vector<int> ans;
        queue<TreeNode*> q;
public:
    vector<int> levelOrder(TreeNode* root) {
       if(!root)
       return ans;
        q.push(root);
       while(q.size())
       {
           TreeNode* tmp = q.front();
           ans.push_back(tmp->val);
            q.pop();
           if(tmp->left)
                q.push(tmp->left);
            if(tmp->right)
                q.push(tmp->right);
       }
        return ans;
    }
};

复杂度:

  • 时间复杂度:O(N)
  • 空间间复杂度:O(N)

2.从上到下打印二叉树 II

题目链接:https://leetcode-cn.com/problems/cong-shang-dao-xia-da-yin-er-cha-shu-ii-lcof/

剑指offer-31--34二叉树OJ题(C++)_第3张图片

和上面的题思路是一样的,不同的是本题需要一个vector来保存当前层的打印结果
当前层的循环条件:

  • 循环次数为当前层节点数(即队列 queue 长度

动图演示:

剑指offer-31--34二叉树OJ题(C++)_第4张图片

代码如下:

class Solution {
    private:
  
    queue<TreeNode*> q;
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> ans;
        if(!root) return ans;
        q.push(root);
        while(!q.empty())
        {
            vector<int> v;
            int size = q.size();
            while(size)
            {
                TreeNode *tmp = q.front();
                q.pop();
               
                v.push_back(tmp->val);

                if(tmp->left)  q.push(tmp->left);
                if(tmp->right) q.push(tmp->right);
               
                size--;
            }
            ans.push_back(v);
        }
        return ans;
    }
};

复杂度:

  • 时间复杂度 O(N)
  • 空间复杂度 O(N)

3.从上到下打印二叉树 III

题目链接:https://leetcode-cn.com/problems/cong-shang-dao-xia-da-yin-er-cha-shu-iii-lcof/

剑指offer-31--34二叉树OJ题(C++)_第5张图片

和上面的题一样的,这题是偶数层反着打印
我们搞一个flag=1,每次循环*=-1,最后判断一下,当一层打印完后flag=-1就正常打印,flag=1先反转一下,再插入到最后的ans中。这题就不做动图了。

代码如下:

class Solution {
    private:
  
    queue<TreeNode*> q;
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> ans;
        if(!root) return ans;
        q.push(root);
        int falg = 1;
        while(!q.empty())
        {
            falg *= -1;
            vector<int> v;
            int size = q.size();
            
            while(size)
            {
                TreeNode *tmp = q.front();
                q.pop();
              
                 
                v.push_back(tmp->val);
             
                if(tmp->left)  q.push(tmp->left);
                if(tmp->right) q.push(tmp->right);
               
                size--;
                 
            }
             if(falg == -1){
                ans.push_back(v);
             }
          
            else
            {
                reverse(v.begin(),v.end());
                ans.push_back(v);
            }
        }
        return ans;
    }
};

复杂度:

  • 时间复杂度:O(N)
  • 空间复杂度:O(N)

4.二叉搜索树的后序遍历序列

题目链接:https://leetcode-cn.com/problems/er-cha-sou-suo-shu-de-hou-xu-bian-li-xu-lie-lcof/

剑指offer-31--34二叉树OJ题(C++)_第6张图片

这题目和给定中序遍历和后序遍历创建二叉树的题目思路一样,我们看看它给定的数值能不能重建成二叉搜索树

二叉搜索树的性质,右结点比根节点大左结点比根节点小,我们利用这个性质来接着道题
剑指offer-31--34二叉树OJ题(C++)_第7张图片

基本步骤:

  • 递归结束:左区间大于等于右区间,说明此子树节点数量 ≤1 ,无需判别正确性,因此直接返回 true

  • 划分左右子树:
    遍历后序遍历的 [l.r]区间元素,寻找 第一个大于根节点 的节点,索引记为 k 。此时,可划分出左子树区间 [l,k-1] 右子树区间 [k, r - 1]根节点索引 root 。

  • 判断是否为二叉搜索树:
    1.左子树区间 内的所有节点都应 2.右子区间如果有小于根节点的返回false

动图演示:

剑指offer-31--34二叉树OJ题(C++)_第8张图片

代码如下:

class Solution {
     vector<int> res;
public:
    bool verifyPostorder(vector<int>& postorder) {
        res = postorder;
        int n = postorder.size();

        return dfs(0,n-1);
    }
    bool dfs(int l,int r)
    {
        if(l >= r) return true;
        int root = res[r];//根节点
        int k = l;
    
        while(k < r && res[k] < root) k++;//找到左子树区间
        for(int i = k; i < r;++i)
        {
            if(res[i] < root) //右子树中比根节点小,就返回false
            return false;
        }
        return dfs(l,k-1) && dfs(k,r-1);//递归处理左右子树
    }
};

复杂度:

  • 时间复杂度 O(N^2) 每次调用 recur(i,j)recur(i,j) 减去一个根节点,因此递归占用 O(N)最差情况下(即当树退化为链表),每轮递归都需遍历树所有节点,占用 O(N) 。
  • 空间复杂度 O(N) : 最差情况下(即当树退化为链表),递归深度将达到 N 。

你可能感兴趣的:(剑指offer,二叉树,数据结构,剑指offer)