时间复杂度:O(n),空间复杂度:O(n)
解题思路
递归法
最最最最常用的方法,优先遍历左孩子直至为空,如果为空就返回然后将根节点的值放入数组中,再从右孩子开始重复以上步骤。
扩展:如果是先序遍历和后序遍历呢?
先序遍历就是优先输出根节点的值,再然后就是遍历左孩子,最后遍历右孩子。
后序遍历就是优先遍历左孩子,然后遍历右孩子,最后输出根节点的值。
通过三者比对应该就会发现先序遍历、中序遍历和后序遍历的递归代码规律了吧。
迭代法
迭代法在做题时不是很常用,因为需要我们自己来维护一个栈,但是它在工程项目中要优于递归法,原因还是我们可以自己维护一个栈,自己来设定栈的大小,不会发生递归时栈溢出的情况。
简单来说就是遇到一个根节点就把它放到栈中,然后再去遍历它的左孩子,直至没有左孩子,那就返回栈顶的结点、输出值,再去找它的右孩子,然后就是重复以上的步骤了。
AC代码
递归法
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func inorderTraversal(root *TreeNode) (res []int) {
var inOrder func(root *TreeNode)//单独声明函数值,防止递归代码编译出错
inOrder=func(root *TreeNode){
if root==nil{
return
}
inOrder(root.Left)
res=append(res,root.Val)
inOrder(root.Right)
}
inOrder(root)
return res
}
迭代法
偷个懒用的官方题解代码,自己加了点注释
func inorderTraversal(root *TreeNode) (res []int) {
stack := []*TreeNode{}
//栈为空就说明遍历完了所有结点
for root != nil || len(stack) > 0 {
for root != nil {
stack = append(stack, root)//令根结点入栈
root = root.Left//优先遍历左孩子
}
//root为空了,接下来保存根节点的值
root = stack[len(stack)-1]//
stack = stack[:len(stack)-1]
res = append(res, root.Val)
root = root.Right//最后才是遍历右孩子
}
return
}
感悟
非常非常基础的中序遍历,第一反应都能想到递归法,但是迭代法也应该学习一下,在企业开发中还是可能会遇到的。