/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func levelOrder(root *TreeNode) []int {
res := make([]int, 0)
if root == nil {
return res
}
var queue []*TreeNode = []*TreeNode{root}
for len(queue) != 0 {
var temp []*TreeNode
for i := 0; i < len(queue); i++ {
item := queue[i]
res = append(res, item.Val)
if item.Left != nil {temp = append(temp, item.Left)}
if item.Right != nil {temp = append(temp, item.Right)}
}
queue = temp
}
return res
}
“`java
class Solution {
public List preorderTraversal(TreeNode root) {
// 使用迭代法(非递归,用栈实现)
Stack stack = new Stack<>();
List result = new ArrayList<>();
if(root==null) return result;
stack.push(root);
while(!stack.isEmpty()){
TreeNode cur = stack.pop();
// 处理中节点
result.add(cur.val);
// 先右后左,处理时才能先左后右
if(cur.right!=null){
stack.push(cur.right);
}
if(cur.left!=null){
stack.push(cur.left);
}
}
return result;
}
public List inorderTraversal(TreeNode root) {
// 中序遍历的迭代写法
// 访问的顺序和处理顺序不一致(前序是一致的)
// 用指针的遍历来访问元素,栈来处理节点上的元素
List result = new ArrayList<>();
Stack stack = new Stack<>();
TreeNode cur = root;
while(cur!=null||!stack.isEmpty()){
if(cur!=null){
stack.push(cur);
// 一直访问左
cur = cur.left;
} else{
// 为空,处理
cur = stack.pop();
result.add(cur.val);
cur = cur.right;
}
}
return result;
}
public List postorderTraversal(TreeNode root) {
// 前序是中左右,后序是左右中
// 中左右->中右左->左右中(逆序)
List result = new ArrayList<>();
Stack stack = new Stack<>();
if(rootnull) return result;
stack.push(root);
while(!stack.isEmpty()){
TreeNode cur = stack.pop();
result.add(cur.val);
if(cur.left!=null) stack.push(cur.left);
if(cur.right!=null) stack.push(cur.right);
}
Collections.reverse(result);
return result;
}
}
时间复杂度:O(n)
空间复杂度:O(n)
共以下 15 个回答
先序遍历
中序遍历
public int[] levelOrderDFS(TreeNode root) { stack = new Stack<>();
//辅助栈
Stack
//辅助节点
TreeNode node = root;
while (node != null || !stack.isEmpty()){
//迭代访问节点的左孩子
while (node != null) {
//入栈
stack.push(node);
node = node.left;
}
后序遍历
打印二叉树
“`java preorderTraversal(TreeNode root) { stack = new Stack<>(); result = new ArrayList<>();
class Solution {
public List
// 使用迭代法(非递归,用栈实现)
Stack
List
if(root==null) return result;
stack.push(root);
while(!stack.isEmpty()){
TreeNode cur = stack.pop();
// 处理中节点
result.add(cur.val);
// 先右后左,处理时才能先左后右
if(cur.right!=null){
stack.push(cur.right);
}
if(cur.left!=null){
stack.push(cur.left);
}
}
return result;
}
public List inorderTraversal(TreeNode root) { result = new ArrayList<>(); stack = new Stack<>();
// 中序遍历的迭代写法
// 访问的顺序和处理顺序不一致(前序是一致的)
// 用指针的遍历来访问元素,栈来处理节点上的元素
List
Stack
TreeNode cur = root;
while(cur!=null||!stack.isEmpty()){
if(cur!=null){
stack.push(cur);
// 一直访问左
cur = cur.left;
} else{
// 为空,处理
cur = stack.pop();
result.add(cur.val);
cur = cur.right;
}
}
return result;
}
public List postorderTraversal(TreeNode root) { result = new ArrayList<>(); stack = new Stack<>();
// 前序是中左右,后序是左右中
// 中左右->中右左->左右中(逆序)
List
Stack
if(rootnull) return result;
stack.push(root);
while(!stack.isEmpty()){
TreeNode cur = stack.pop();
result.add(cur.val);
if(cur.left!=null) stack.push(cur.left);
if(cur.right!=null) stack.push(cur.right);
}
Collections.reverse(result);
return result;
}
}
时间复杂度:O(n)
空间复杂度:O(n)
时空间复杂度:O(n)
栈和迭代法解决:思路:访问节点入栈,要处理的节点也入栈,但是做好标记,用null空指针标记 也叫做标记法
用栈实现
八
”’java preorderTraversal(TreeNode root){ re = new ArrayList<>();
//前序遍历
//递归法
class Solution{
public List
List
preorderTraversal(root,re);
return re;
}
//迭代法 preorderTraversal(TreeNode root){ res = new ArrayList<>(); stack = new Stack<>();
class Solution{
public List
List
if(root null){
return res;
}
Stack
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;
}
}
//迭代法前序遍历 preorderTraversal(TreeNode root){ result = new LinkedList<>(); st = new Stack<>(); postorderTraversal(TreeNode root){ re = new ArrayList<>(); re){
class Solution{
public List
List
Stack
if(root != null){
st.push(root);
}
while(!st.empty()){
TreeNode node = st.peek();
if(node != null){
st.pop();
if(node.right != null){
st.push(node.right);
}
if(node.left != null){
st.push(node.left);
}
st.push(node);
st.push(null);
}else{
st.pop();
node = st.peek();
st.pop();
result.add(node.val);
}
}
return result;
}
}
//后序遍历
//递归法
class Solution{
public List
List
postorderTraversal(root,re);
return re;
}
public void postorderTraversal(TreeNode root,List
if(root null){
return;
}
postorderTraversal(root.left,re);
postorderTraversal(root.right,re);
re.add(root.val);
}
//迭代法 postorderTraversal(TreeNode root){ res = new ArrayList<>(); stack = new Stack<>(); null || root.right prev){ inorderTraversal(TreeNode root) { re = new ArrayList<>(); re){ null){
class Solution{
public List
List
if(root null){
return res;
}
Stack
TreeNode prev = null;
while(root != null || !stack.isEmpty()){
while(root != null){
stack.push(root);
root = root.left;
}
root = stack.pop();
if(root.right
res.add(root.val);
prev = root;
root = null;
}else{
stack.push(root);
root = root.right;
}
}
return res;
}
}
//中序遍历
//递归
class Solution {
public List
List
inorderTraversal(root,re);
return re;
}
public void inorderTraversal(TreeNode root,List
if(root
return;
}
inorderTraversal(root.left,re);
re.add(root.val);
inorderTraversal(root.right,re);
}
}
//迭代 inorderTraversal(TreeNode root){ re = new ArrayList<>(); stack = new Stack<>();
class Solution{
public List
List
Stack
if(root null){
return re;
}
while(!stack.isEmpty() || root != null){
while(root != null){
stack.push(root);
root = root.left;
}
root = stack.pop();
re.add(root.val);
root = root.right;
}
return re;
}
}
时间复杂度:O(n)
空间复杂度O(n)
”’
二叉树的遍历
以下会通过递归和迭代两种方法来实现二叉树的遍历,并通过前中后序三种方式来表达。
首先给出前序、后序、中序三种情况在leetcode上对应的题目。
二叉树的前序遍历
二叉树的后序遍历
二叉树的中序遍历
递归
首先,递归需要记住以下三个步骤,可以解决大部分的递归问题的逻辑:
1. 确定递归函数的参数和返回值: 明确哪些参数是要参与递归过程的,以及确定每次递归的返回值。
2. 确定终止条件: 如果递归没有终止,那么就会造成溢出。
3. 确定单层递归的逻辑: 确定每一层递归需要完成的内容。
前序遍历
思路
代码
后序遍历
思路
和前序遍历一样,进行三个步骤的思考。基本一致,就是在单层逻辑上用后序遍历的思想,按照左右中的顺序。
代码
中序遍历
思路
一致。使用中序遍历的顺序,左中右进行输入。
代码
迭代(非递归)
递归的实质就是每一次递归都会把函数的局部变量、参数值和返回地址等压入调用栈中,然后在递归返回的时候,栈顶弹出上一次递归的各项参数,所以这就是递归可以返回上一层位置的原因。
所以这里我们也可以用栈来实现二叉树的前中后序遍历。
前序遍历
思路
前序遍历是中左右,每次先处理中间节点,所以先加入根节点,然后放入右节点,最后放入左节点。
为什么明明是中左右的顺序,但是在进入栈的时候要中 右 左 呢?
因为根节点在入栈之后最先出栈了,完成了中左右的中。但是左右子树还要分别向下迭代,由于栈是先进后出的,所以需要让左先出栈的话,右子树需要先进入栈中。
代码
后序遍历
思路
前序遍历是中左右,后序遍历是左右中,这里可以通过几次变换得到。
前序遍历:中左右。
通过调换左右的入栈顺序可以得到中间过程:中右左
然后进行整个数组的反转可以得到:左右中,即后序遍历
代码
中序遍历
思路
中序遍历的过程和前序后序不太一样,由于不是先处理中,但是得先运行到中,即处理和运行顺序不一致,所以不好直接对中进行简单处理。这里需要用指针来进行遍历。由于中序遍历是左中右,所以要先遍历到左子树的最左下角的节点,然后再进行输出,期间要保存每个路径的节点信息到数组。
代码
前序
中序
后序
1) 递归:
2) 迭代
1) 递归
2) 迭代
1) 递归
2) 迭代