理论基础
需要了解 二叉树的种类,存储方式,遍历方式 以及二叉树的定义
144.二叉树的前序遍历
二叉树前序遍历口诀: 中左右
注: 在使用迭代来完成二叉树的前序遍历很简单。carl哥的代码随想录中两句很重要的话:
-
在企业项目开发中,尽量不要使用递归!项目较大时,参数多,全局变量等等。使用递归很容易判断不充分return的条件
-
递归的实现就是:每一次递归调用都会把函数的局部变量、参数值和返回地址等压入到调用栈中。 ——即可理解为,递归能够实现的,我们都能够尝试使用栈来实现。
1、先使用递归来实现
/**
* Definition for a binary tree node.
* 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;
* }
* }
*/
class Solution {
//因为要使用递归的方式,所以函数的返回值必须是void 故而额外创建了一个函数,用来真正地前序遍历
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> result=new ArrayList<>();
preOrder(root,result);
return result;
}
//注意:一开始我将result设置成了static。提交时就发现static会一直随着测试用例而不断累积变化
//它只会在最开始时初始化,这个是一定要注意的
public void preOrder(TreeNode root,List<Integer> result){
//先使用递归来实现
//前序遍历:中左右
if(root==null){
return;
}
result.add(root.val);
preOrder(root.left,result);
preOrder(root.right,result);
}
}
2、使用迭代来实现
如前面所说,使用迭代遍历来顶替递归,一般都要使用栈。
这里回顾一下栈和队列
Java中栈和队列一般初试化是这样(以元素为Integer类型为例):
//栈
Stack<Integer>stack=new Stack<>(); //初始化栈
stack.push(4); //入栈
stack.pop(); //出栈
——————
Queue<Integer> queue=new LinkedList<>();//初始化队列
queue.offer(4); //入队
queue.poll();//出队
/**
* Definition for a binary tree node.
* 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;
* }
* }
*/
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer>result=new ArrayList<>();
Stack<TreeNode> stack=new Stack<>();
if(root==null){
return result;
}
//先把根节点压入栈
stack.push(root);
while(!stack.isEmpty()){
//因为是二叉树的前序遍历——中左右。
//第一步一定是先访问“自己”,所以要先pop
TreeNode node=stack.pop();
//可以进行模拟,因为遍历顺序是“中左右”,所以要右子节点先入栈,再是左入栈
result.add(node.val);
if(node.right!=null)
stack.push(node.right);
if(node.left!=null)
stack.push(node.left);
}
return result;
}
}
94.二叉树的中序遍历
使用递归——与前序遍历的递归算法没有太大的变化
/**
* Definition for a binary tree node.
* 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;
* }
* }
*/
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> result=new ArrayList<>();
inOrder(root,result);
return result;
}
public void inOrder(TreeNode root,List<Integer>result){
if(root==null)
return;
//二叉树的中序遍历:左中右
inOrder(root.left,result);
result.add(root.val);
inOrder(root.right,result);
}
}
2、使用迭代
二叉树的中序遍历的迭代和前序遍历的迭代方法不同,最明显的不同在于二叉树的中序遍历中处理顺序与访问顺序是不一致的。
-
个人记录/警醒:在最初思考的时候,由于要使用栈,下意识地想从根节点root一直往右子树寻找,不断将右子树压栈,然后再pop出来进而访问左子树。
-
但是这个最大的问题在于:它违背了二叉树中序遍历的规则——左中右,我应该顺着其规则来进行模拟。在其左子树上进行模拟,试着通过栈来探索到方法。
-
/**
* Definition for a binary tree node.
* 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;
* }
* }
*/
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> result=new ArrayList<>();
Stack<TreeNode>stack=new Stack<>();
if(root==null)
return result;
TreeNode node=root;
while( node!=null || !stack.isEmpty()){
//如果当前节点不为空,则压栈,然后往左走
if(node!=null){
stack.push(node);
node=node.left;
}
//如果当前节点的左子节点为空,那么就pop出栈,加入到result中
//同时向其右子节点遍历
else{
node=stack.pop();
result.add(node.val);
node=node.right;
}
}
return result;
}
}
145.二叉树的后序遍历
/**
* Definition for a binary tree node.
* 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;
* }
* }
*/
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> result=new ArrayList<>();
postOrder(root,result);
return result;
}
public void postOrder(TreeNode root,List<Integer> result){
if(root==null)
return;
postOrder(root.left,result);
postOrder(root.right,result);
result.add(root.val);
}
}
递归:
2、二叉树的后续遍历--迭代方法
二叉树的后序遍历和其前序遍历顺序正好相反,故而可以直接用前序遍历的代码,然后最后结果reverse