--------------------------2020/12/29---------------------------
收获:for循环的时候队列的长度会变化,所以得先用一个变量存储,感觉就没有其他难点了

32-I

//广度优先
/*** 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:vector<int> levelOrder(TreeNode* root) {if(!root) return {};vector<int> ans;queue <TreeNode*> que;que.push(root);while(!que.empty()) {TreeNode* tmp = que.front();que.pop();ans.push_back(tmp -> val);if(tmp -> left != NULL) que.push(tmp -> left);if(tmp -> right != NULL) que.push(tmp -> right);    }return ans;}
};

32-II

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

32-III


class Solution {public:vector<vector<int>> levelOrder(TreeNode* root) {if(!root) return {};int flag = 1;//从左向右取数字vector<vector<int>> ans;deque<TreeNode*> d;d.push_back(root);while(!d.empty()) {vector<int> tmp;int len = d.size();for(int i = 0; i < len; i ++) {if(flag == 1) {TreeNode* cur = d.front();d.pop_front();tmp.push_back(cur -> val);if(cur -> left) d.push_back(cur -> left);if(cur -> right) d.push_back(cur -> right);}else {TreeNode* cur = d.back();d.pop_back();tmp.push_back(cur -> val);if(cur -> right) d.push_front(cur -> right);if(cur -> left) d.push_front(cur -> left);}    }flag = !flag;ans.push_back(tmp);}return ans;}
};

--------------------------一刷----------------------------------
之前一直在做深度优先的题目,导致广度优先有点生疏了
先稍微复习一下:
一般而言,深度优先利用递归的方式,走到没有路时回溯至上一个还有路的点;
广度优先利用队列存储的方式,当队列不为空时不断往外扩张从而走遍所有路径。
通过啊哈算法中比较经典的计算小岛面积的问题来直观感受两者的区别
ps:只是最基础的模板,代码没有优化,且根据书上原代码,队列借助数组实现

//深度优先遍历
void dfs(int x, int y) {int k, tx, ty;for(int k = 0; k <= 3; k++) {tx = x + next[k][0];//next数组定义为四个方向ty = y + next[k][1];if(越界) continue;if(为陆地并且点尚未走过){sum ++;//小岛面积book[x][y]=1;//标记该点走过dfs(tx, ty);//一走到底}}return ;}//广度优先遍历
void bfs(int x, int y) {while(head < tail) {int k, tx, ty;for(int k = 0; k<= 3; k++) {tx = que[head].x + next[k][0];//next数组定义为四个方向ty = que[head].y + next[k][1];if(越界) continue;if(为陆地并且点尚未走过){sum ++;//小岛面积book[x][y]=1;//标记该点走过que[tail].x = tx;que[tail].y = ty;tail++;}}head++;//层层递进}
}

而对二叉树的广度优先遍历(又称为二叉树的层次遍历)的区别只在于其遍历方向只有两个->左子树和右子树,于是可以得到代码

class Solution {public:vector<int> levelOrder(TreeNode* root) {if(root == NULL)return {};queue <TreeNode*> que;vector <int> ans;que.push(root);while(!que.empty()) {TreeNode* cur = que.front();que.pop();//do somethingif(cur -> left != NULL) que.push(cur -> left);if(cur -> right != NULL) que.push(cur -> right);}return ans;}
};

12-I题目描述

解法BFS

/*** 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:vector<int> levelOrder(TreeNode* root) {if(root == NULL)return {};queue <TreeNode*> que;vector <int> ans;que.push(root);while(!que.empty()) {TreeNode* cur = que.front();que.pop();ans.push_back(cur -> val);if(cur -> left != NULL) que.push(cur -> left);if(cur -> right != NULL) que.push(cur -> right);}return ans;}
};


时间复杂度O(n),空间复杂度O(n)

12-II 题目描述

解法

多增加了每层的边境判定,由于二叉树层次遍历的特性,我们能通过队列的长度得知该层需要处理的结点个数。
或者重复2^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:vector<vector<int>> levelOrder(TreeNode* root) {vector<vector<int>> ans;if(root == NULL)return {};queue <TreeNode*> que;que.push(root);while(!que.empty()) {vector<int> tmp;int len = que.size();for(int i = 0; i < len ; i++) {//for循环结束说明这层处理结束TreeNode* cur = que.front();que.pop();tmp.push_back(cur -> val);if(cur -> left != NULL) que.push(cur -> left);if(cur -> right != NULL) que.push(cur -> right);}ans.push_back(tmp);}return ans;}
};

要注意到que.push并不是在做这一层的事情,而是在压入下一层的结点,防止对12-III的处理出现误解
时间复杂度O(n),空间复杂度O(n);

12-III题目描述

解法一 vector倒转

利用vector倒转实现,简单粗暴,告诉面试官之后就能等通知了

class Solution {public:vector<vector<int>> levelOrder(TreeNode* root) {int flag=0;vector<vector<int>> ans;if(root == NULL)return {};queue <TreeNode*> que;que.push(root);while(!que.empty()) {vector<int> tmp;int len = que.size();for(int i = 0; i < len ; i++) {TreeNode* cur = que.front();que.pop();tmp.push_back(cur -> val);if(cur -> left != NULL) que.push(cur -> left);if(cur -> right != NULL) que.push(cur -> right);}if(flag == 1) {reverse(tmp.begin(), tmp.end());flag=0;}else flag=1;ans.push_back(tmp);}return ans;}
};

解法deque

也是一个比较少用到的数据结构,所以来复习一下deque
直接转载另一篇博客了deque知识点
简单来说就是可以两边都可以删除增加元素的队列


class Solution {public:vector<vector<int>> levelOrder(TreeNode* root) {int flag=0;//0从左到右 1从右到左vector<vector<int>> ans;if(root == NULL)return {};deque <TreeNode*> d;d.push_front(root);while(!d.empty()) {vector<int> tmp;int len = d.size();for(int i = 0; i < len ; i++) {if(flag == 0) {TreeNode* cur = d.front();d.pop_front();tmp.push_back(cur -> val);if(cur -> left != NULL) d.push_back(cur -> left);if(cur -> right != NULL) d.push_back(cur -> right);}else {TreeNode* cur = d.back();d.pop_back();tmp.push_back(cur -> val);if(cur -> right != NULL) d.push_front(cur -> right);if(cur -> left != NULL) d.push_front(cur -> left);}}flag = !flag;ans.push_back(tmp);}return ans;}
};

中间的部分比较绕
根据第二题可得每一层都是一次完整的for循环,所以可以把从左到右的情况和从右到左的情况分开分析。
当从左到右时,从deque的首部取元素(也就是上一层的最后一个元素),然后以从左到右的顺序压入deque的尾部。
当从右到左时,从deque的尾部取元素(也就是上一层的最后一个元素),然后以从右到左的顺序压入deque的头部。
比如例题中的二叉树

顺序

  1. 3入队
  2. 第一次for循环flag=0 从左到右
 TreeNode* cur = d.front();
d.pop_front();
tmp.push_back(cur -> val);
if(cur -> left != NULL) d.push_back(cur -> left);
if(cur -> right != NULL) d.push_back(cur -> right);
 3出队列 9 20从后端入队   tmp={3} deque={9,20}
  1. 第二次for循环flag=1 从右到左
TreeNode* cur = d.back();
d.pop_back();
tmp.push_back(cur -> val);
if(cur -> right != NULL) d.push_front(cur -> right);
if(cur -> left != NULL) d.push_front(cur -> left);
20出队  NULL NULL入队 tmp={20}  deque={9}
9出队  7 15前端入队   tmp={20,9} deque{15,7}
  1. 第三次for循环flag=0 从左到右
 TreeNode* cur = d.front();
d.pop_front();
tmp.push_back(cur -> val);
if(cur -> left != NULL) d.push_back(cur -> left);
if(cur -> right != NULL) d.push_back(cur -> right);

15出队 NULL tmp={15} deque={}
7出队 NULL tmp={15,7} deque={}
总之就是按照之字的顺序把元素丢到deque中,并且要保证丢入元素顺序和上一层相反,同时不能影响到上一层元素的出队。
画个图来看,其实从左到右的元素次序并没有变化,变的只是从后往前取和从前往后取。

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

剑指 Offer 32-I/32-II/32-III从上到下打印二叉树c++相关推荐

  1. [剑指offer][JAVA]面试题第[32-1]题[从上到下打印二叉树][BFS]

    [问题描述][中等] 从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印. 例如: 给定二叉树: [3,9,20,null,null,15,7],3/ \9 20/ \15 7 返回: ...

  2. [剑指offer][JAVA]面试题第[32-3]题[从上到下打印二叉树 ][BFS]

    [问题描述][中等] 请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推. 例如: 给定二叉树: [3 ...

  3. [剑指offer][JAVA]面试题第[32-2]题[从上到下打印二叉树][BFS]

    [问题描述][简单] 从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印到一行.例如: 给定二叉树: [3,9,20,null,null,15,7],3/ \9 20/ \15 7 ...

  4. 【LeetCode】剑指 Offer 32 - III. 从上到下打印二叉树 III

    [LeetCode]剑指 Offer 32 - III. 从上到下打印二叉树 III 文章目录 [LeetCode]剑指 Offer 32 - III. 从上到下打印二叉树 III package o ...

  5. leetcode 打印_剑指 Offer 32 - III 从上到下打印二叉树 III - leetcode 剑指offer

    题目难度: 中等 原题链接 今天继续更新剑指 offer 系列, 这道题相比昨天那道题多了个每层打印方向不同的需求, 聪明的你想到应该如何实现了吗? 老样子晚上 6 点 45 分准时更新公众号 每日精 ...

  6. 【最佳解法】剑指 Offer 32 - III. 从上到下打印二叉树 III

    立志用最少的代码做最高效的表达 请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推. 例如: 给定二叉 ...

  7. 32 - III. 从上到下打印二叉树 III

    链接 https://leetcode-cn.com/problems/cong-shang-dao-xia-da-yin-er-cha-shu-iii-lcof/ 难度: #中等 题目 请实现一个函 ...

  8. 剑指offer:面试题32 - III. 从上到下打印二叉树 III

    题目: 从上到下打印二叉树 III 请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推. 例如: 给定 ...

  9. 剑指Offer - 面试题32 - III. 从上到下打印二叉树 III(BFS,queue+stack)

    1. 题目 请实现一个函数按照之字形顺序打印二叉树, 即第一行按照从左到右的顺序打印, 第二层按照从右到左的顺序打印, 第三行再按照从左到右的顺序打印,其他行以此类推. 例如: 给定二叉树: [3,9 ...

  10. 剑指offer面试题32 - III. 从上到下打印二叉树 III(二叉树)(BFS)

    题目描述 请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推. 思路 详见链接 代码 class So ...

最新文章

  1. 还在担心工作被AI取代?不如掌握这门硬实力,抢占职场发展机遇
  2. jquery源码解析:jQuery数据缓存机制详解2
  3. 'objects' 报错问题
  4. 获取minist数据并转换成lmdb
  5. quartz定时器依赖_JAVA使用quartz添加定时任务,并依赖注入对象操作
  6. PULSE:一种基于隐式空间的图像超分辨率算法
  7. linux串口进单用户模式,进入SUSE Linux Enterprise Server 12系统单用户模式的方法
  8. 【集合】Vector 是线程安全的?
  9. 线程间通信 1全局变量2当前主对话框指针3发消息方式4 AfxBeginThread的返回值(为CWinThread类型的指针)5AfxGetApp...
  10. 飞机上终于能开着手机连 Wi-Fi 了,它背后的技术原理是什么?
  11. matlab2014b linux,matlab 2014b linux 肿么安装
  12. D3D游戏关于窗口中如何精确确定鼠标位置的相关讨论
  13. php制作的教师管理信息系统,php师资信息管理系统
  14. wifi的html页面,笔记本怎么设置wifi
  15. CAD关于图层删除图层操作(com接口c#语言)
  16. 阿龙的学习笔记---MySQL45讲的总结(一)
  17. uniapp app引入谷歌地图
  18. centons7安装docker私有库harbor
  19. 题目34 众数和中位数
  20. 云计算大数据之 Java 操作 Kafka

热门文章

  1. c语言 常量和变量 ppt,c语言常量与变量.ppt
  2. 【渝粤题库】广东开放大学 汉语基础 形成性考核
  3. 体检套餐管理系统 C#
  4. 对称矩形C语言,c语言编程求任意对称正定矩阵的逆。
  5. 再抱一抱DataStore
  6. 生活小妙招:办公室如何查看自己电脑已连接的无线网密码,记得收藏
  7. Spring Bean的生命周期自我记忆
  8. PYTHON判断回文素数
  9. 【ZZULIOJ】1097: 计算平均成绩(函数专题)
  10. 家园2简易地图编辑器