题目一 剑指 Offer 32 - I. 从上到下打印二叉树

来源:力扣(LeetCode)

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

1.描述

从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印。

2.示例

  • 示例 1:
给定二叉树: [3,9,20,null,null,15,7],

    3
/ \
9 20
/ \
15 7
返回: [3,9,20,15,7]

解法一 广度优先遍历+辅助队列

解题思路

看到题不难想到最简单的办法就是借助一个队列,对二叉树进行广度优先遍历。

1.如果根节点为空,直接返回空数组,否则入队根节点;

2.将队头节点值加入答案数组;

3.入队队头节点的非空子节点,将队头节点出队。

4.重复2,3过程直到队列为空。

代码

/**
* 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) {
vector<int> ans;//存储答案
if(!root) return ans;//如果根节点为空,返回空答案数组
queue<TreeNode*> q;//辅助队列
q.push(root);//根节点入队
while(!q.empty()){//只要队列不为空
ans.push_back(q.front()->val);//将队头节点值加入答案数组
//入队队头节点的非空子节点
if(q.front()->left) q.push(q.front()->left);
if(q.front()->right) q.push(q.front()->right);
q.pop();//将队头节点出队
}
return ans;//返回答案
}
};

复杂度分析

时间复杂度: O(m)m二叉树节点数,遍历整棵二叉树需要O(m)时间。

空间复杂度: O(m)。存储答案和使用辅助队列的空间消耗。

解法二 深度优先搜索+辅助数组

解题思路

除了解法一较为直观的广度优先搜索外,我们也可以使用深度优先搜索+辅助二维数组解决本题。

具体的,我们对二叉树进行深度优先搜索,同时维护一个层数level,初始时level0。每进入一层递归,也即从当前节点遍历孩子节点时,层数就加一,然后通过层数作为下标访问二维数组将节点值加入对应层的一维数组,最后再将二维数组按层捋直即为最终答案。

代码

/**
* 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) {
vector<int> ans;//存储答案
if(!root) return ans;//如果根节点为空,返回空数组
vector<vector<int>> aid;//辅助数组
dfs(root, 0, aid);//深度优先遍历
for(auto a : aid) ans.insert(ans.end(), a.begin(), a.end());//将二维数组按层捋直
return ans; //返回答案
} void dfs(TreeNode* root, int level, vector<vector<int>>& aid){
if(!root) return;//如果节点为空,返回
if(aid.size()<=level){//如果该层数组还未创建,创建之
vector<int> temp;
aid.push_back(temp);
}
aid[level].push_back(root->val);//将节点值加入对应层数组
dfs(root->left, level+1, aid);//遍历左子节点,同时level+1
dfs(root->right, level+1, aid);//遍历右子节点,同时level+1
}
};

复杂度分析

时间复杂度: O(m)。递归以及把二维数组捋直的时间消耗

空间复杂度: O(m)。递归以及辅助数组、答案数组的空间消耗。

题目二 剑指 Offer 32 - II. 从上到下打印二叉树 II

来源:力扣(LeetCode)

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

1.描述

从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印到一行。

2.示例

  • 示例 1:
给定二叉树: [3,9,20,null,null,15,7],

    3
/ \
9 20
/ \
15 7
返回其层次遍历结果: [
[3],
[9,20],
[15,7]
]

解法一 广度优先搜索+辅助队列

解题思路

参考题目一,我们可以写出广度优先搜索+辅助队列的版本。

不过略有不同的是,我们需要选择合适的方式进行分层。这里使用两个额外变量countsize进行分层操作,对每一层,size为层大小,初始时为1,即只有根节点的时候队列的大小。每记录一个节点,count值加一,当count等于size时,表示当前层已遍历完毕,则更新层大小,重置count0

1.如果根节点为空,直接返回空数组,否则入队根节点;

2.将队头节点值加入答案数组;

3.入队队头节点的非空子节点,将队头节点出队;

4.将count加一,若count等于size,则更新size,并重置count0

5.重复2,34过程直到队列为空。

代码

/**
* 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) return ans;//如果根节点为空,返回空数组
queue<TreeNode*> q;//辅助队列
q.push(root);//入队根节点
int size = q.size(), count = 0;//初始化size和count
vector<int> temp;//辅助数组
while(!q.empty()){//只要队列不为空
temp.push_back(q.front()->val);//记录队头节点值
//入队队头节点的非空子节点
if(q.front()->left) q.push(q.front()->left);
if(q.front()->right) q.push(q.front()->right);
q.pop();//出队队头节点
++count;//将count+1
if(count == size){//若count==size,表示当前层已记录完毕
ans.push_back(temp);//将temp加入答案数组
temp.clear();//清空temp
count = 0;//重置count为0
size = q.size();//更新size
}
}
return ans;//返回答案
}
};

复杂度分析

时间复杂度: O(m)m为二叉树节点数,遍历整棵二叉树需要O(m)时间。

空间复杂度: O(m)。辅助队列,答案数组,辅助数组的空间消耗。

解法二 深度优先搜索+辅助数组

解题思路

除了解法一较为直观的广度优先搜索外,我们也可以使用深度优先搜索+辅助二维数组解决本题。

具体的,我们对二叉树进行深度优先搜索,同时维护一个层数level,初始时level0。每进入一层递归,也即从当前节点遍历孩子节点时,层数就加一,然后通过层数作为下标访问二维数组将节点值加入对应层的一维数组,遍历完成后即为最终答案。

代码

/**
* 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) return ans;//如果根节点为空,返回空数组
dfs(root, 0, ans);//深度优先遍历
return ans;//返回答案
} void dfs(TreeNode* root, int level, vector<vector<int>>& aid){//深度优先遍历
if(!root) return;//如果节点为空,直接返回
if(aid.size()<=level){//如果当前层数组还未创建,创建之
vector<int> temp;
aid.push_back(temp);
}
aid[level].push_back(root->val);//存入当前节点值到对应层
dfs(root->left, level+1, aid);//遍历左孩子,层数加一
dfs(root->right, level+1, aid);//遍历右孩子,层数加一
}
};

复杂度分析

时间复杂度: O(m)。遍历二叉树的时间消耗。

空间复杂度: O(m)。存储答案和递归的栈空间消耗。

题目三 剑指 Offer 32 - III. 从上到下打印二叉树 III

来源:力扣(LeetCode)

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

1.描述

请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推。

2.示例

  • 示例 1:
给定二叉树: [3,9,20,null,null,15,7],

    3
/ \
9 20
/ \
15 7
返回其层次遍历结果: [
[3],
[20,9],
[15,7]
]

解法一 广度优先搜索+辅助队列

解题思路

参考题目二,我们可以写出广度优先搜索+辅助队列的版本。

我们需要选择合适的方式进行分层。这里使用两个额外变量countsize进行分层操作,对每一层,size为层大小,初始时为1,即只有根节点的时候队列的大小。每记录一个节点,count值加一,当count等于size时,表示当前层已遍历完毕,则更新层大小,重置count0。不过略有不同的是,我们需要在遍历完毕后对结果数组进行处理,也即翻转偶数层数组。处理完毕后即为答案。

1.如果根节点为空,直接返回空数组,否则入队根节点;

2.将队头节点值加入答案数组;

3.入队队头节点的非空子节点,将队头节点出队;

4.将count加一,若count等于size,则更新size,并重置count0

5.重复2,34过程直到队列为空;

6.翻转偶数层结果数组。

代码

/**
* 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) return ans;//如果根节点为空,返回空数组
queue<TreeNode*> q;//辅助队列
q.push(root);//入队根节点
int size = q.size(), count = 0;//初始化size和count
vector<int> temp;//辅助数组
while(!q.empty()){//只要队列不为空
temp.push_back(q.front()->val);//记录队头节点值
//入队队头节点的非空子节点
if(q.front()->left) q.push(q.front()->left);
if(q.front()->right) q.push(q.front()->right);
q.pop();//出队队头节点
++count;//将count+1
if(count == size){//若count==size,表示当前层已记录完毕
ans.push_back(temp);//将temp加入答案数组
temp.clear();//清空temp
count = 0;//重置count为0
size = q.size();//更新size
}
}
for(int i = 0; i < m; ++i) if(i%2!=0) reverse(ans[i].begin(), ans[i].end());//翻转偶数层
return ans;//返回答案
}
};

复杂度分析

时间复杂度: O(m)m为二叉树节点数,遍历整棵二叉树和翻转偶数层需要O(m)时间。

空间复杂度: O(m)。辅助队列,答案数组,辅助数组的空间消耗。

解法二 深度优先遍历+辅助数组

解题思路

这里也提供深度优先遍历的版本。

代码

/**
* 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) return ans;//如果根节点为空,返回空数组
dfs(root, 0, ans);//深度优先遍历
for(int i = 0; i < m; ++i) if(i%2!=0) reverse(ans[i].begin(), ans[i].end());//翻转偶数层
return ans;//返回答案
} void dfs(TreeNode* root, int level, vector<vector<int>>& aid){//深度优先遍历
if(!root) return;//如果节点为空,直接返回
if(aid.size()<=level){//如果当前层数组还未创建,创建之
vector<int> temp;
aid.push_back(temp);
}
aid[level].push_back(root->val);//存入当前节点值到对应层
dfs(root->left, level+1, aid);//遍历左孩子,层数加一
dfs(root->right, level+1, aid);//遍历右孩子,层数加一
}
};

复杂度分析

时间复杂度: O(m)。遍历二叉树和翻转偶数层的时间消耗。

空间复杂度: O(m)。存储答案和递归的栈空间消耗。

一般说来,广度优先遍历更直观,但是代码较长;而深度优先遍历代码简洁,但是较难理解。要多用多练,以掌握之。

更多知识内容分享:

博客园个人主页https://home.cnblogs.com/u/newCoderTheWarrior

力扣个人主页https://leetcode-cn.com/profile/articles/

【Warrior刷题笔记】剑指offer 32. 三道题,让你学会二叉树的深度广度优先遍历与递归迭代技术的更多相关文章

  1. 【Java】 剑指offer(32) 从上往下打印二叉树

    本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集   题目 (一)从上往下打印出二叉树的每个结点,同一层的结点按照从左到右的顺 ...

  2. 二维数组的查找,刷题成功——剑指Offer

    今天又做了一道题目,通过啦,欧耶! https://www.nowcoder.net/practice/abc3fe2ce8e146608e868a70efebf62e?tpId=13&tqI ...

  3. Leetcode刷题记录 剑指offer

    面试题3:数组中重复数字 # 使用set,时间复杂度O(n),空间复杂度O(n)class Solution(object): def findRepeatNumber(self, nums): &q ...

  4. #刷题记录--剑指 Offer 07. 重建二叉树

    输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树.假设输入的前序遍历和中序遍历的结果中都不含重复的数字. 抓住一点,通过递归进行节点创建时,是按照 前序遍历数组 进行创建的. 根节点,根节点的左 ...

  5. 剑指offer——32从上到下打印二叉树

    题目描述 从上往下打印出二叉树的每个节点,同层节点从左至右打印.   题解: 就是简单的层序遍历 class Solution { public: vector<int> PrintFro ...

  6. 剑指 Offer 32 - I. 从上到下打印二叉树 + 层次遍历二叉树

    剑指 Offer 32 - I. 从上到下打印二叉树 Offer_32_1 题目描述 解题思路 这题属于简单题,考察的是我们对二叉树以及层次遍历的方法. 这里只需要使用简单的队列即可完成二叉树的层次遍 ...

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

    剑指 Offer 32 - III. 从上到下打印二叉树 III 请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印, ...

  8. 剑指 Offer 32 - I. 从上到下打印二叉树

    剑指 Offer 32 - I. 从上到下打印二叉树 从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印. 例如: 给定二叉树: [3,9,20,null,null,15,7], 3 ...

  9. 剑指 Offer 32 - III. 从上到下打印二叉树 III + 双端队列使用 + 蛇形打印层次遍历序列 + 正倒序输出

    剑指 Offer 32 - III. 从上到下打印二叉树 III Offer_32_3 题目详情 题解分析 本题我想的比较复杂,其实题目的要求只是需要遍历的结果逆序和正序交替,这个其实可以使用Coll ...

随机推荐

  1. 【JAVA今法修真】 第四章 redis特性 击穿雪崩!

    感谢这段时间大家的支持,关注我的微信号:南橘ryc ,回复云小霄,就可以获取到最新的福利靓照一张,还等什么,赶快来加入我们吧~ "明日便是决赛了,咋只会用法器没练过法术呢.". 选 ...

  2. [BUUCTF]PWN——jarvisoj_level3

    jarvisoj_level3 附件 步骤 例行检查,32位,nx保护 运行一下程序 32位ida载入,shift+f12没有看到程序里有可以直接利用的后面函数,根据运行时的字符串找到了程序的关键函数 ...

  3. 统计函数(Excel函数集团)

    此处文章均为本妖原创,供下载.学习.探讨! 文章下载源是Office365国内版1Driver,如有链接问题请联系我. 请勿用于商业! 谢谢 下载地址:https://officecommunity- ...

  4. response.setHeader("xxx","大侠")如果赋值中文,那么将不会在页面出值,

    response.setHeader("xxx","大侠")如果赋值中文,那么将不会在页面出值,而非中文就可以在页面出值

  5. 【LeetCode】966. Vowel Spellchecker 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 字典 日期 题目地址:https://leetcod ...

  6. 【LeetCode】862. Shortest Subarray with Sum at Least K 解题报告(C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 队列 日期 题目地址:https://leetcod ...

  7. 【LeetCode】863. All Nodes Distance K in Binary Tree 解题报告(Python)

    [LeetCode]863. All Nodes Distance K in Binary Tree 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http ...

  8. 获得MATLAB中FIG文件的矩阵

    在拓扑优化中,经常使用imagesc函数来显示最终的结果,往往会保存了Fig文件,却忘记保存mat文件. 根据已有的Fig文件,是可以找到其所显示矩阵.这个是我从fig数据结构中一层一层找到的,记录一 ...

  9. 【LeetCode】811. Subdomain Visit Count 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 字典统计次数 日期 题目地址:https://lee ...

  10. hdu-3183A Magic Lamp(贪心)

    题目的意思是: 给你一个大数,然后删减其中的K个数,并且剩下的数还是按原来在的先后次序排列,求所得的那个数最小的那个数. 思路:贪心(要取得数最小,你从左往右选数的时候,选的第一数,就是选后组成数的位 ...