刷题---树篇---94. 二叉树的中序遍历
程序员文章站
2024-01-11 17:08:16
...
给定一个二叉树,返回它的中序 遍历。
难度:中等
示例:
输入: [1,null,2,3]
1
\
2
/
3
输出: [1,3,2]
进阶: 递归算法很简单,你可以通过迭代算法完成吗?
———————————————————————————————————————————————————————
这本应该是一道基础题,基础的中序遍历算法。但是题目给了个要求,用迭代完成,这应该就是本题为中等难度的原因。
go递归版本:
func inorderTraversal(root *TreeNode) []int {
res := make([]int,0)
if root == nil {
return res
}
Run(root,&res)
return res
}
func Run(root *TreeNode, num *[]int) {
if root == nil {
return
}
Run(root.Left,num)
*num = append(*num,root.Val)
Run(root.Right,num)
}
go非递归版本:
func inorderTraversal(root *TreeNode) []int {
res := make([]int,0)
if root == nil {
return res
}
//手动维护一个栈
stack := make([]*TreeNode,0)
k := root
for len(stack) != 0 || k != nil{
//若此时节点为nil,则不入栈
//否则入栈
for k != nil {
stack = append(stack,k)
k = k.Left
}
//出栈操作
k = stack[len(stack)-1]
stack = stack[:len(stack)-1]
res = append(res,k.Val)
//按照中序遍历原则,左-中-右
//有右则入右
k = k.Right
}
return res
}
我对这一解法的理解是:
按照中序遍历原则,左-中-右,则对于某一节点的入栈规则为:
先入自己,再入左子树,再入右子树。
当某一节点存在右子节点的时候,采取的方法是将右子节点入栈,作为下次循环的栈顶再进行处理。
在循环条件的选择:for len(stack) != 0 || k != nil
当栈为空且此时的节点为空时则结束循环,因为此时没有任何值得处理的节点。
换句话说,只有栈中有节点,则必须处理栈中的节点,只要节点k不为空,则必须处理节点k。
如图所示:
方法二:
func inorderTraversal(root *TreeNode) []int {
stack := make([]*TreeNode,0)
res := make([]int,0)
if root == nil {
return res
}
push(&stack,root)
for len(stack) != 0 {
for root.Left != nil {
push(&stack,root.Left)
root = root.Left
}
root,stack = pop(stack)
root.Left = nil
res = append(res,root.Val)
if root.Right != nil {
push(&stack,root.Right)
root = root.Right
}
}
return res
}
func push(stack *[]*TreeNode,t *TreeNode) {
*stack = append(*stack,t)
}
func pop(stack []*TreeNode) (*TreeNode,[]*TreeNode) {
t := stack[len(stack)-1]
stack = stack[:len(stack)-1]
return t,stack
}