本篇文章给大家分享一下二叉树的相关算法。
前言
一、题目介绍
1.1二叉树前序遍历
我们都知道二叉树有三种遍历方式,分别是前序遍历、中序遍历和后序遍历,每一种遍历都有不同的性质,大家在后期的做题过程中可能会用到一些遍历的性质,所以请注意这块的性质!
三种遍历都是类似的,就是输出的顺序有所不同,会一种基本其余的两种也就会写了。
示例 1:
输入:root = [1,null,2,3]
输出:[1,2,3]
示例 2:
输入:root = []
输出:[]
1.2 二叉树展开为链表
给定一个二叉树,原地将它展开为一个单链表。其实仔细分析题目,这就是前序输出二叉树,这里介绍的也是最容易想到的思路,官方还给了另外的两种思路,大家可以到这里查看!
示例 1:
二、解题思路
1.分析题目
当拿到二叉树类型的题目的时候,就要往这方面的内容进行思考,比如三种遍历方式、还有就是深度优先搜索和广度优先搜索这块思考,基本常见的也就是这几种题目。
2.二叉树的前序遍历
对于二叉树的前序遍历,我们可以使用递归和迭代的方式进行遍历。
2.2.1递归
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
preorder(root, res);//递归调用
return res;
}
public void preorder(TreeNode root, List<Integer> res) {
if (root == null) {
return;
}
res.add(root.val);//根节点
preorder(root.left, res);//左子树
preorder(root.right, res);//右子树
}
}
复杂度分析
- 时间复杂度:O(n)O(n),其中 nn 是二叉树的节点数。每一个节点恰好被遍历一次。
- 空间复杂度:O(n)O(n),为递归过程中栈的开销,平均情况下为 O(\log n)O(logn),最坏情况下树呈现链状,为
O(n)O(n)。
2.2.2迭代
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
if (root == null) {
return res;
}
Deque<TreeNode> stack = new LinkedList<TreeNode>();
TreeNode node = root;
while (!stack.isEmpty() || node != null) {
while (node != null) {
res.add(node.val);
stack.push(node);
node = node.left;
}
node = stack.pop();
node = node.right;
}
return res;
}
}
复杂度分析
- 时间复杂度:O(n)O(n),其中 nn 是二叉树的节点数。每一个节点恰好被遍历一次。
- 空间复杂度:O(n)O(n),为迭代过程中显式栈的开销,平均情况下为 O(\log n)O(logn),最坏情况下树呈现链状,为
O(n)O(n)。
3.代码
3.1题目一:二叉树前序遍历
Java代码详细注释
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<>();//创建list
preTree(root,result);//递归遍历
return result;
}
public void preTree(TreeNode root,List<Integer> result){
if(root!=null){
result.add(root.val);
preTree(root.left,result);
preTree(root.right,result);
}
}
}
3.2题目二: 二叉树展开为链表
将二叉树展开为单链表之后,单链表中的节点顺序即为二叉树的前序遍历访问各节点的顺序。因此,可以对二叉树进行前序遍历,获得各节点被访问到的顺序。由于将二叉树展开为链表之后会破坏二叉树的结构,因此在前序遍历结束之后更新每个节点的左右子节点的信息,将二叉树展开为单链表。
Java代码详细注释
class Solution {
public void flatten(TreeNode root) {
List<TreeNode> list = new ArrayList<>();
preTree(root,list);//前序遍历二叉树
int size = list.size();//链表的长度
for(int i=1;i<size;i++){
TreeNode pre = list.get(i-1),curr = list.get(i);
pre.left = null;
pre.right = curr;
}
}
//二叉树的递归先序遍历
public void preTree(TreeNode root,List<TreeNode> list){
if(root!=null){
list.add(root);
preTree(root.left,list);
preTree(root.right,list);
}
}
}
三、总结
树这块的题目基本都是有套路可寻的,所以大家在平时多加练习的同时,一定要熟记相关的套路,思路找好,模板一套,齐活!
记录时间:2020年12月22日