1. 二叉树的结构定义
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() {}
TreeNode(int val) { this.val = val; }
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
2. 递归遍历
题目链接:
2.1 递归三要素
- 确定递归函数的参数和返回值
- 确定终止条件
- 确定单层递归的逻辑
2.2 代码
前序:中左右 中序:左中右 后序:左右中
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<>();
front(root, list);
return list;
}
public void front(TreeNode cur, List<Integer> list){
if(cur==null) return;
//中左右
list.add(cur.val);
front(cur.left, list);
front(cur.right, list);
}
}
3. 迭代遍历
递归的实现就是:每一次递归调用都会把函数的局部变量、参数值和返回地址等压入调用栈中
所以迭代遍历使用栈去实现
3.1 前序遍历
使用栈实现前序遍历,即中左右,放置顺序为中右左,只有这样从栈里取出的元素顺序符合要求
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<>();
Stack<TreeNode> stack = new Stack<>();
if(root==null) return list;
stack.push(root);
while(!stack.isEmpty()){
TreeNode node = stack.pop();
list.add(node.val);
if(node.right!=null) {
stack.add(node.right);
}
if(node.left!=null){
stack.add(node.left);
}
}
return list;
}
}
3.2 后序遍历
有点抽象
3.3 中序遍历
访问的顺序和要处理(放入到list中)的顺序不一致
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
//访问顺序和处理顺序不一致
//使用一个指针去后序遍历,将需要处理的先放在栈中
Stack<TreeNode> stack = new Stack<>();
List<Integer> list = new ArrayList<>();
TreeNode cur = root;
while(cur!=null || !stack.isEmpty()){
if(cur!=null){
stack.add(cur);
cur = cur.left;
}else{
cur = stack.pop();
list.add(cur.val);
cur = cur.right;
}
}
return list;
}
}
4. 层序遍历
使用队列,将每层元素放置进去,每次弹出元素时,将该元素的左右节点放置进队列,最后使用二维数组将其存起来
102. 二叉树的层序遍历
关键点:用队列实现。队列先进先出,层序遍历也属于先遍历到的先取
lass Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
return checkFunc(root);
}
public List<List<Integer>> checkFunc(TreeNode root){
List<List<Integer>> resultList = new ArrayList<>();
//顶点额外处理
if(root==null) return resultList;
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);
while(!queue.isEmpty()){
List<Integer> itemList = new ArrayList<>();
int size = queue.size();
while(size>0){
TreeNode node = queue.poll();
itemList.add(node.val);
//⏰第一次写不仔细 将node写成了root,一直超过时间限制
if(node.left!=null) queue.add(node.left);
if(node.right!=null) queue.add(node.right);
size--;
}
resultList.add(itemList);
}
return resultList;
}
}
107. 二叉树的层次遍历 II
关键点:自底向上遍历,将自顶向下的结果反转(for循环从后至前)即可
109. 二叉树的右视图
- 递归法
class Solution {
public List<Integer> rightSideView(TreeNode root) {
List<Integer> list = new ArrayList<>();
return right(root, list);
}
private List<Integer> right(TreeNode root, List<Integer> list){
if(root==null) return list;
list.add(root.val);
return right(root.right, list);
}
}
- 层序遍历法
class Solution {
public List<Integer> rightSideView(TreeNode root) {
//使用层序遍历:队列 每层每层放进去 ,除了每层最后一个,其他元素全部poll()
Queue<TreeNode> queue = new LinkedList<>();
List<Integer> list = new ArrayList<>();
if(root==null) return list;
queue.add(root);
while(!queue.isEmpty()){
int size = queue.size();
for(int i=0; i<size; i++){
TreeNode node = queue.poll();
if(node.left!=null){
queue.add(node.left);
}
if(node.right!=null){
queue.add(node.right);
}
if(i==size-1){
list.add(node.val);
}
}
}
return list;
}
}
637. 二叉树的层平均值
class Solution {
public List<Double> averageOfLevels(TreeNode root) {
Queue<TreeNode> queue = new LinkedList<>();
List<Double> list = new ArrayList<>();
if(root==null) return list;
queue.add(root);
while(!queue.isEmpty()){
int size = queue.size();
Double sum = 0.0;
for(int i=0; i<size; i++){
TreeNode node = queue.poll();
if(node.left!=null){
queue.add(node.left);
}
if(node.right!=null){
queue.add(node.right);
}
sum += node.val;
}
list.add(sum/size);
}
return list;
}
}
5. 总结
- 深度遍历:用先进后出的栈实现
- 层序遍历:用先进先出的队列实现
- 递归法
- 迭代法(非递归方式)