【二叉树遍历入门:从中序遍历到层序与右视图】【LeetCode 热题100】94:二叉树的中序遍历、102:二叉树的层序遍历、199:二叉树的右视图(详细解析)(Go语言版)

简介: 本文详细解析了二叉树的三种经典遍历方式:中序遍历(94题)、层序遍历(102题)和右视图(199题)。通过递归与迭代实现中序遍历,深入理解深度优先搜索(DFS);借助队列完成层序遍历和右视图,掌握广度优先搜索(BFS)。文章对比DFS与BFS的思维方式,总结不同遍历的应用场景,为后续构造树结构奠定基础。

🌳 二叉树遍历入门:从中序遍历到层序与右视图

本文涵盖 LeetCode 上的三道基础但极具代表性的二叉树遍历题:

    1. 二叉树的中序遍历
    1. 二叉树的层序遍历
    1. 二叉树的右视图

通过这些题目,我们将从 DFS 到 BFS,深入理解如何处理树结构的不同维度信息。


🧩 题目一:94. 二叉树的中序遍历

📝 题目描述

给定一棵二叉树,返回它的中序遍历
中序遍历顺序:左子树 → 根节点 → 右子树


💡 解题思路

中序遍历是深度优先搜索(DFS)中的一种经典形式。我们可以通过递归(最自然)或迭代(更贴近底层执行过程)两种方式来完成。


✅ 解法一:递归

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

🧠 思路总结

递归的核心是“做当前,交给子问题”,结构上非常清晰。


✅ 解法二:迭代(用栈模拟)

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

📌 注意点:

  • 用一个 while 循环控制整体流程。
  • 用一个内嵌的 for 循环不断向左深入。
  • 弹栈后处理当前节点,再转向右子树。

🧩 题目二:102. 二叉树的层序遍历

📝 题目描述

返回一个按层次遍历(每一层从左到右)的节点值数组。


💡 解题思路

层序遍历就是经典的广度优先搜索(BFS),借助队列来完成逐层访问。


✅ 解法:使用队列 BFS

func levelOrder(root *TreeNode) [][]int {
   
    if root == nil {
   
        return [][]int{
   }
    }
    res := [][]int{
   }
    queue := []*TreeNode{
   root}
    for len(queue) > 0 {
   
        level := []int{
   }
        size := len(queue)
        for i := 0; i < size; i++ {
   
            node := queue[0]
            queue = queue[1:]
            level = append(level, node.Val)
            if node.Left != nil {
   
                queue = append(queue, node.Left)
            }
            if node.Right != nil {
   
                queue = append(queue, node.Right)
            }
        }
        res = append(res, level)
    }
    return res
}

📌 关键点:

  • 使用 queue 存储当前层的所有节点。
  • 通过 size 确定每层的边界。
  • 每层遍历完成后将其加入结果集。

🧩 题目三:199. 二叉树的右视图

📝 题目描述

从右侧观察一棵二叉树,返回你能看到的节点值。


💡 解题思路

本质还是 BFS,只不过我们只关心每一层的最后一个节点。


✅ 解法:BFS + 每层最后一个节点

func rightSideView(root *TreeNode) []int {
   
    if root == nil {
   
        return []int{
   }
    }
    res := []int{
   }
    queue := []*TreeNode{
   root}
    for len(queue) > 0 {
   
        size := len(queue)
        for i := 0; i < size; i++ {
   
            node := queue[0]
            queue = queue[1:]
            if i == size-1 {
   
                res = append(res, node.Val)
            }
            if node.Left != nil {
   
                queue = append(queue, node.Left)
            }
            if node.Right != nil {
   
                queue = append(queue, node.Right)
            }
        }
    }
    return res
}

📌 细节提示:

  • 每层的最后一个节点 i == size - 1 才加入结果。
  • 和层序遍历一样,使用 queue 来按层推进。

🧠 总结与反思

遍历类型 算法 数据结构 应用
中序遍历 DFS 栈 / 递归 搜索树性质、线索二叉树
层序遍历 BFS 队列 可视化结构、层级分析
右视图 BFS 队列 一层一个视角节点
  • DFS 与 BFS 的思维方式差异是树结构的关键入门点。
  • 掌握递归与迭代切换思维,对后续复杂结构建树、剪枝、遍历非常重要。

下一篇我们将探索如何通过遍历构造树结构(前序 + 中序 → 构造二叉树、数组 → 平衡搜索树等),敬请期待!

目录
相关文章
|
2月前
|
Cloud Native 安全 Java
Go语言深度解析:从入门到精通的完整指南
🌟蒋星熠Jaxonic,Go语言探索者。深耕云计算、微服务与并发编程,以代码为笔,在二进制星河中书写极客诗篇。分享Go核心原理、性能优化与实战架构,助力开发者掌握云原生时代利器。#Go语言 #并发编程 #性能优化
432 43
Go语言深度解析:从入门到精通的完整指南
|
3月前
|
Cloud Native 安全 Java
Go语言深度解析:从入门到精通的完整指南
🌟 蒋星熠Jaxonic,执着的星际旅人,用Go语言编写代码诗篇。🚀 Go语言以简洁、高效、并发为核心,助力云计算与微服务革新。📚 本文详解Go语法、并发模型、性能优化与实战案例,助你掌握现代编程精髓。🌌 从goroutine到channel,从内存优化到高并发架构,全面解析Go的强大力量。🔧 实战构建高性能Web服务,展现Go在云原生时代的无限可能。✨ 附技术对比、最佳实践与生态全景,带你踏上Go语言的星辰征途。#Go语言 #并发编程 #云原生 #性能优化
|
7月前
|
存储 安全 Go
Map的遍历与判断键是否存在-《Go语言实战指南》
本文介绍了 Go 语言中对 `map` 的常见操作,包括遍历所有项和判断键是否存在。通过 `for range` 可以遍历 `map` 的键值对、仅键或仅值(需忽略键)。注意,`map` 遍历顺序是随机的。判断键是否存在时,使用双赋值语法 `value, ok := map[key]`,其中 `ok` 表示键是否存在。直接访问不存在的键会返回类型的零值,可能导致逻辑错误。掌握这些机制可更安全高效地处理键值对数据。
|
7月前
|
Go 开发者 索引
【LeetCode 热题100】路径与祖先:二叉树中的深度追踪技巧(力扣33 / 81/ 153/154)(Go语言版)
本文深入探讨了LeetCode中四道关于「搜索旋转排序数组」的经典题目,涵盖了无重复和有重复元素的情况。通过二分查找的变形应用,文章详细解析了每道题的解题思路和Go语言实现代码。关键点包括判断有序区间、处理重复元素以及如何缩小搜索范围。文章还总结了各题的异同,并推荐了类似题目,帮助读者全面掌握二分查找在旋转数组中的应用。无论是初学者还是有经验的开发者,都能从中获得实用的解题技巧和代码实现方法。
327 14
|
6月前
|
Go
【LeetCode 热题100】DP 实战进阶:最长递增子序列、乘积最大子数组、分割等和子集(力扣300 / 152/ 416 )(Go语言版)
本文深入解析三道经典的动态规划问题:**最长递增子序列(LIS)**、**乘积最大子数组** 和 **分割等和子集**。 - **300. LIS** 通过 `dp[i]` 表示以第 `i` 个元素结尾的最长递增子序列长度,支持 O(n²) 动态规划与 O(n log n) 的二分优化。 - **152. 乘积最大子数组** 利用正负数特性,同时维护最大值与最小值的状态转移方程。 - **416. 分割等和子集** 转化为 0-1 背包问题,通过布尔型 DP 实现子集和判断。 总结对比了三题的状态定义与解法技巧,并延伸至相关变种问题,助你掌握动态规划的核心思想与灵活应用!
283 1
|
6月前
|
分布式计算 算法 Go
【LeetCode 热题100】BFS/DFS 实战:岛屿数量 & 腐烂的橘子(力扣200 / 994 )(Go语言版)
本文讲解了两道经典的图论问题:**岛屿数量(LeetCode 200)** 和 **腐烂的橘子(LeetCode 994)**,分别通过 DFS/BFS 实现。在“岛屿数量”中,利用深度或广度优先搜索遍历二维网格,标记连通陆地并计数;“腐烂的橘子”则采用多源 BFS,模拟腐烂传播过程,计算最短时间。两者均需掌握访问标记技巧,是学习网格搜索算法的绝佳实践。
282 1
|
7月前
|
存储 算法 Go
【LeetCode 热题100】17:电话号码的字母组合(详细解析)(Go语言版)
LeetCode 17题解题思路采用回溯算法,通过递归构建所有可能的组合。关键点包括:每位数字对应多个字母,依次尝试;递归构建下一个字符;递归出口为组合长度等于输入数字长度。Go语言实现中,使用map存储数字到字母的映射,通过回溯函数递归生成组合。时间复杂度为O(3^n * 4^m),空间复杂度为O(n)。类似题目包括括号生成、组合、全排列等。掌握回溯法的核心思想,能够解决多种排列组合问题。
307 11
|
7月前
|
Go
【LeetCode 热题100】155:最小栈(详细解析)(Go语言版)
本文详细解析了力扣热题155:最小栈的解题思路与实现方法。题目要求设计一个支持 push、核心思路是使用辅助栈法,通过两个栈(主栈和辅助栈)来维护当前栈中的最小值。具体操作包括:push 时同步更新辅助栈,pop 时检查是否需要弹出辅助栈的栈顶,getMin 时直接返回辅助栈的栈顶。文章还提供了 Go 语言的实现代码,并对复杂度进行了分析。此外,还介绍了单栈 + 差值记录法的进阶思路,并总结了常见易错点,如 pop 操作时忘记同步弹出辅助栈等。
256 6
|
6月前
|
Go
【LeetCode 热题100】BFS/DFS 实战:岛屿数量 & 腐烂的橘子(力扣200 / 994 )(Go语言版)
本篇博客详细解析了三道经典的动态规划问题:198. 打家劫舍(线性状态转移)、279. 完全平方数与322. 零钱兑换(完全背包问题)。通过 Go 语言实现,帮助读者掌握动态规划的核心思想及其实战技巧。从状态定义到转移方程,逐步剖析每道题的解法,并总结其异同点,助力解决更复杂的 DP 问题。适合初学者深入理解动态规划的应用场景和优化方法。
220 0
|
6月前
|
算法 Go 索引
【LeetCode 热题100】回溯:括号生成 & 组合总和(力扣22 / 39 )(Go语言版)
本文深入解析了LeetCode上的两道经典回溯算法题:**22. 括号生成**与**39. 组合总和**。括号生成通过维护左右括号数量,确保路径合法并构造有效组合;组合总和则允许元素重复选择,利用剪枝优化搜索空间以找到所有满足目标和的组合。两者均需明确路径、选择列表及结束条件,同时合理运用剪枝策略提升效率。文章附有Go语言实现代码,助你掌握回溯算法的核心思想。
255 0