代码随想录算法训练营Day14

86 阅读4分钟

代码随想录算法训练营Day14

二叉树节点结构定义

二叉树节点结构定义如下:

type TreeNode struct {
	Val   int
	Left  *TreeNode
	Right *TreeNode
}

二叉树递归遍历

前序遍历算法设计步骤

  1. 确定递归函数的参数和返回值
    • 参数:当前节点指针
    • 返回值:前序遍历序列数组
  2. 确定终止条件
    • 当前节点为空时,返回空数组
  3. 确定单层递归的逻辑
    • 将当前节点的值加入遍历序列数组
    • 递归遍历左子树
    • 递归遍历右子树

前序遍历代码实现

func preorderTraversal(root *TreeNode) []int {
    if root == nil {
        return []int{}
    }
    result := []int{root.Val}
    result = append(result, preorderTraversal(root.Left)...)
    result = append(result, preorderTraversal(root.Right)...)
    return result
}

中序遍历算法设计步骤

  1. 确定递归函数的参数和返回值
    • 参数:当前节点指针
    • 返回值:中序遍历序列数组
  2. 确定终止条件
    • 当前节点为空时,返回空数组
  3. 确定单层递归的逻辑
    • 递归遍历左子树
    • 将当前节点的值加入遍历序列数组
    • 递归遍历右子树

中序遍历代码实现

func inorderTraversal(root *TreeNode) []int {
    if root == nil {
        return []int{}
    }
    result := []int{}
    result = append(result, inorderTraversal(root.Left)...)
    result = append(result, root.Val)
    result = append(result, inorderTraversal(root.Right)...)
    return result
}

后序遍历算法设计步骤

  1. 确定递归函数的参数和返回值
    • 参数:当前节点指针
    • 返回值:后序遍历序列数组
  2. 确定终止条件
    • 当前节点为空时,返回空数组
  3. 确定单层递归的逻辑
    • 递归遍历左子树
    • 递归遍历右子树
    • 将当前节点的值加入遍历序列数组

后序遍历的Go语言实现代码

func postorderTraversal(root *TreeNode) []int {
    if root == nil {
        return []int{}
    }
    result := []int{}
    result = append(result, postorderTraversal(root.Left)...)
    result = append(result, postorderTraversal(root.Right)...)
    result = append(result, root.Val)
    return result
}

二叉树迭代遍历

前序遍历的迭代法算法设计步骤

  1. 确定递归函数的参数和返回值
    • 参数:根节点指针
    • 返回值:前序遍历序列数组
  2. 确定终止条件
    • 当当前节点为空时,终止遍历
  3. 确定单层递归的逻辑
    • 使用栈来模拟递归过程
    • 将根节点压入栈中
    • 循环直到栈为空,每次弹出栈顶节点,将节点值加入遍历序列数组
    • 如果节点的右子树不为空,将右子树压入栈中
    • 如果节点的左子树不为空,将左子树压入栈中

前序遍历的迭代法代码实现

func preorderTraversal(root *TreeNode) []int {
    var result []int
    if root == nil {
        return result
    }
    stack := []*TreeNode{root}
    for len(stack) > 0 {
        node := stack[len(stack)-1]
        stack = stack[:len(stack)-1]
        result = append(result, node.Val)
        if node.Right != nil {
            stack = append(stack, node.Right)
        }
        if node.Left != nil {
            stack = append(stack, node.Left)
        }
    }
    return result
}

中序遍历的迭代法算法设计步骤

  1. 确定递归函数的参数和返回值
    • 参数:根节点指针
    • 返回值:中序遍历序列数组
  2. 确定终止条件
    • 当当前节点为空且栈为空时,终止遍历
  3. 确定单层递归的逻辑
    • 使用栈来模拟递归过程
    • 从根节点开始,将所有左子节点压入栈中
    • 弹出栈顶节点,将节点值加入遍历序列数组
    • 如果节点有右子节点,将右子节点及其所有左子节点压入栈中

中序遍历的迭代法算法代码实现

func inorderTraversal(root *TreeNode) []int {
    var result []int
    stack := []*TreeNode{}
    node := root
    for node != nil || len(stack) > 0 {
        for node != nil {
            stack = append(stack, node)
            node = node.Left
        }
        node = stack[len(stack)-1]
        stack = stack[:len(stack)-1]
        result = append(result, node.Val)
        node = node.Right
    }
    return result
}

后序遍历的迭代法算法设计步骤

  1. 确定递归函数的参数和返回值
    • 参数:根节点指针
    • 返回值:后序遍历序列数组
  2. 确定终止条件
    • 当当前节点为空且栈为空时,终止遍历
  3. 确定单层递归的逻辑
    • 使用两个栈来模拟递归过程
    • 将根节点压入第一个栈中
    • 从第一个栈中弹出节点,并将节点值压入第二个栈中
    • 如果节点有左子节点,将左子节点压入第一个栈中
    • 如果节点有右子节点,将右子节点压入第一个栈中

后序遍历的迭代法算法代码实现

func postorderTraversal(root *TreeNode) []int {
    var result []int
    if root == nil {
        return result
    }
    stack1 := []*TreeNode{root}
    stack2 := []*TreeNode{}
    for len(stack1) > 0 {
        node := stack1[len(stack1)-1]
        stack1 = stack1[:len(stack1)-1]
        stack2 = append(stack2, node)
        if node.Left != nil {
            stack1 = append(stack1, node.Left)
        }
        if node.Right != nil {
            stack1 = append(stack1, node.Right)
        }
    }
    for i := len(stack2) - 1; i >= 0; i-- {
        result = append(result, stack2[i].Val)
    }
    return result
}