废话不多说,喊一句号子鼓励自己:程序员永不失业,程序员走向架构!本篇Blog的主题是【二叉树的遍历】,使用【二叉树】这个基本的数据结构来实现,这个高频题的站点是:CodeTop,筛选条件为:目标公司+最近一年+出现频率排序,由高到低的去牛客TOP101去找,只有两个地方都出现过才做这道题(CodeTop本身汇聚了LeetCode的来源),确保刷的题都是高频要面试考的题。
就着这两个高频题目把二叉树的遍历类型题目刷一遍
名曲目标题后,附上题目链接,后期可以依据解题思路反复快速练习,题目按照题干的基本数据结构分类,且每个分类的第一篇必定是对基础数据结构的介绍。
二叉树的前序遍历【EASY】
前序、中序、后序都有迭代和递归的实现方式
题干
解题思路
前序遍历简单来说就是“根左右”,展开来说就是对于一颗二叉树优先访问其根节点,然后访问它的左子树,等左子树全部访问完了再访问其右子树,而对于子树也按照之前的访问方式,直到到达叶子节点,每次访问一个节点之后,它的左子树是一个要前序遍历的子问题,它的右子树同样是一个要前序遍历的子问题。那我们可以用递归处理:
- 终止条件: 当子问题到达叶子节点后,后一个不管左右都是空,因此遇到空节点就返回。
- 返回值: 每次处理完子问题后,就是将子问题访问过的元素返回,依次存入了数组中。
- 本级任务: 每个子问题优先访问这棵子树的根节点,然后递归进入左子树和右子树。
具体做法:
step 1:准备数组用来记录遍历到的节点值,Java可以用List
step 2:从根节点开始进入递归,遇到空节点就返回,否则将该节点值加入数组。
step 3:依次进入左右子树进行递归。
代码实现
给出代码实现基本档案
其中数据结构、算法和技巧分别来自:
- 10 个数据结构:数组、链表、栈、队列、散列表、二叉树、堆、跳表、图、Trie 树
- 10 个算法:递归、排序、二分查找、搜索、哈希算法、贪心算法、分治算法、回溯算法、动态规划、字符串匹配算法
- 技巧:双指针、滑动窗口、中心扩散
当然包括但不限于以上
import java.util.*;
/*
* public class TreeNode {
* int val = 0;
* TreeNode left = null;
* TreeNode right = null;
* public TreeNode(int val) {
* this.val = val;
* }
* }
*/
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param root TreeNode类
* @return int整型一维数组
*/
public int[] preorderTraversal (TreeNode root) {
// 1 定义用来返回的数据
List<Integer> list = new ArrayList<>();
// 2 递归填充list的值
preorder(list, root);
// 3 返回结果处理
int[] result = new int[list.size()];
for (int i = 0; i < list.size(); i++) {
result[i] = list.get(i);
}
return result;
}
private void preorder(List<Integer> list, TreeNode root) {
// 1 递归终止条件
if (root == null) {
return;
}
// 2 按顺序递归填充左右子树
list.add(root.val);
preorder(list, root.left);
preorder(list, root.right);
}
}
复杂度分析
时间复杂度:遍历了N个节点,所以时间复杂度为O(N)
空间复杂度:最坏情况下,树退化为链表,递归栈深度为N,所以空间复杂度为O(N)
二叉树的中序遍历【EASY】
换位中序遍历
题干
解题思路
如果一棵二叉树,对于每个根节点都优先访问左子树,那结果是什么?从根节点开始不断往左,第一个被访问的肯定是最左边的节点。然后访问该节点的右子树,最后向上回到父问题。因为每次访问最左的元素不止对一整棵二叉树成立,而是对所有子问题都成立,因此循环的时候自然最开始都是遍历到最左,然后访问,然后再进入右子树,我们可以用栈来实现回归父问题
- 寻找最左子树,此过程逐层将树及左子树的根节点压入栈中,把要后处理的上层子树根节点先压入操作栈
- 栈顶即当前最左子树根节点,也是上层子树的左子节点,将值放入到list
- 节点指针移动到当前指针右节点,如果右节点为空,则本层处理完成,栈再弹出上层节点,接着循环处理
其实思路与递归就相似了,只不过将递归栈具象化了
代码实现
递归的思路和代码不再赘述,直接给出
import java.util.*;
/*
* public class TreeNode {
* int val = 0;
* TreeNode left = null;
* TreeNode right = null;
* public TreeNode(int val) {
* this.val = val;
* }
* }
*/
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param root TreeNode类
* @return int整型一维数组
*/
public int[] inorderTraversal (TreeNode root) {
// 1 定义入参和返回值
List<Integer> list = new ArrayList<>();
// 2 中序递归获取list
inorder(list, root);
// 3 list结果转换
int[] result = new int[list.size()];
for (int i = 0; i < list.size(); i++) {
result[i] = list.get(i);
}
return result;
}
private void inorder(List<Integer> list, TreeNode root) {
// 1 终止条件
if (root == null) {
return;
}
inorder(list, root.left);
list.add(root.val);
inorder(list, root.right);
}
}
给出代码实现基本档案
其中数据结构、算法和技巧分别来自:
- 10 个数据结构:数组、链表、栈、队列、散列表、二叉树、堆、跳表、图、Trie 树
- 10 个算法:递归、排序、二分查找、搜索、哈希算法、贪心算法、分治算法、回溯算法、动态规划、字符串匹配算法
- 技巧:双指针、滑动窗口、中心扩散
当然包括但不限于以上
import java.util.*;
/*
* public class TreeNode {
* int val = 0;
* TreeNode left = null;
* TreeNode right = null;
* public TreeNode(int val) {
* this.val = val;
* }
* }
*/
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param root TreeNode类
* @return int整型一维数组
*/
public int[] inorderTraversal (TreeNode root) {
// 1 定义入参和辅助栈
List<Integer> list = new ArrayList<>();
Stack<TreeNode> stack = new Stack<TreeNode>();
if (root == null) {
return new int[0];
}
// 2 寻找最左子树
TreeNode tempRoot = root;
while (tempRoot != null || !stack.isEmpty()) {
// 2-1 寻找最左子树,此过程逐层将树及左子树的根节点压入栈中
while (tempRoot != null) {
// 把要后处理的上层子树根节点先压入操作栈
stack.push(tempRoot);
tempRoot = tempRoot.left;
}
// 2-2 栈顶即当前最左子树根节点,也是上层子树的左子节点
TreeNode node = stack.pop();
list.add(node.val);
// 2-3 节点指针移动到当前指针右节点,如果右节点为空,则本层处理完成,栈再弹出上层节点
tempRoot = node.right;
}
// 3 list结果转换
int[] result = new int[list.size()];
for (int i = 0; i < list.size(); i++) {
result[i] = list.get(i);
}
return result;
}
}
复杂度分析
时间复杂度:遍历了N个节点,所以时间复杂度为O(N)
空间复杂度:最坏情况下,树退化为链表,辅助递归栈深度为N,所以空间复杂度为O(N)
二叉树的后序遍历【EASY】
ok,再来看二叉树的后序遍历
题干
解题思路
左右根,同前序遍历及中序遍历的递归解法,不再赘述
代码实现
给出代码实现基本档案
其中数据结构、算法和技巧分别来自:
- 10 个数据结构:数组、链表、栈、队列、散列表、二叉树、堆、跳表、图、Trie 树
- 10 个算法:递归、排序、二分查找、搜索、哈希算法、贪心算法、分治算法、回溯算法、动态规划、字符串匹配算法
- 技巧:双指针、滑动窗口、中心扩散
当然包括但不限于以上
import java.util.*;
/*
* public class TreeNode {
* int val = 0;
* TreeNode left = null;
* TreeNode right = null;
* public TreeNode(int val) {
* this.val = val;
* }
* }
*/
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param root TreeNode类
* @return int整型一维数组
*/
public int[] postorderTraversal (TreeNode root) {
// 1 定义用来返回的数据
List<Integer> list = new ArrayList<>();
// 2 递归填充list的值
postorder(list, root);
// 3 返回结果处理
int[] result = new int[list.size()];
for (int i = 0; i < list.size(); i++) {
result[i] = list.get(i);
}
return result;
}
private void postorder(List<Integer> list, TreeNode root) {
if (root == null) {
return;
}
postorder(list, root.left);
postorder(list, root.right);
list.add(root.val);
}
}
复杂度分析
时间复杂度:遍历了N个节点,所以时间复杂度为O(N)
空间复杂度:最坏情况下,树退化为链表,递归栈深度为N,所以空间复杂度为O(N)
二叉树的层序遍历【MID】
题干
直接粘题干和用例
解题思路
给出解题思路,最好有图
代码实现
给出代码实现基本档案
其中数据结构、算法和技巧分别来自:
- 10 个数据结构:数组、链表、栈、队列、散列表、二叉树、堆、跳表、图、Trie 树
- 10 个算法:递归、排序、二分查找、搜索、哈希算法、贪心算法、分治算法、回溯算法、动态规划、字符串匹配算法
- 技巧:双指针、滑动窗口、中心扩散
当然包括但不限于以上
复杂度分析
时间复杂度:
空间复杂度:
二叉树的锯齿形层序遍历【MID】
题干
直接粘题干和用例
解题思路
给出解题思路,最好有图
代码实现
给出代码实现基本档案
其中数据结构、算法和技巧分别来自:
- 10 个数据结构:数组、链表、栈、队列、散列表、二叉树、堆、跳表、图、Trie 树
- 10 个算法:递归、排序、二分查找、搜索、哈希算法、贪心算法、分治算法、回溯算法、动态规划、字符串匹配算法
- 技巧:双指针、滑动窗口、中心扩散
当然包括但不限于以上
复杂度分析
时间复杂度:
空间复杂度:
二叉树的右视图【MID】
题干
直接粘题干和用例
解题思路
给出解题思路,最好有图
代码实现
给出代码实现基本档案
其中数据结构、算法和技巧分别来自:
- 10 个数据结构:数组、链表、栈、队列、散列表、二叉树、堆、跳表、图、Trie 树
- 10 个算法:递归、排序、二分查找、搜索、哈希算法、贪心算法、分治算法、回溯算法、动态规划、字符串匹配算法
- 技巧:双指针、滑动窗口、中心扩散
当然包括但不限于以上
复杂度分析
时间复杂度:
空间复杂度:
拓展知识
关联与本题相关的辅助知识点