[LeetCode]二叉树层次遍历讲解与实例
来源:互联网 发布:matlab分水岭分割算法 编辑:程序博客网 时间:2024/06/15 20:16
[LeetCode]二叉树层次遍历讲解与实例
0.题目
leetcode : 199. Binary Tree Right Side View
1.题目描述
Given a binary tree, imagine yourself standing on the right side of it, return the values of the nodes you can see ordered from top to bottom.
For example:
Given the following binary tree,
1 <--- / \2 3 <--- \ \ 5 4 <---
You should return [1, 3, 4].
2.题目分析
题目大意是让我们输出一棵二叉树每一层最右边的一个节点的数值。
我们一般是通过深度优先搜索(DFS)对二叉树进行遍历的,例如三种遍历方式:先序遍历,中序遍历,后序遍历,详细的讲解可以看这篇博客根据树的遍历还原树.
一般情况下,深度优先搜索是通过栈实现的,虽然我们在遍历的时候没有使用递归,看似没有使用栈,但是要记住递归也是通过栈实现,下面给大家一种普适的通过栈实现深度优先搜索的代码
stack<int> DFS; DFS.push(root); while (DFS.size() != 0) { // need pop first DFS.pop(); DFS.push(DFS.top()->left); DFS.push(DFS.top()->right); // do something there }
上面的代码只是例子,想让大家了解一下如何使用栈来实现深度优先搜索。
通过代码我们可以发现,我们将当前节点的左右子树push进栈,这是节点的值是在栈顶的。而每次我们访问的又恰好是栈顶的元素,这就保证了我们每次都是深度优先。大家最好自己模拟一下遍历过程,这样能更好的理解栈与深度优先搜索的关系。
解决本题使用深度优先搜索比较麻烦(大家可以自己尝试),所以我们要换一种思路–广度优先搜索。
题目要求我们输出每一层最右边的数,我们可以想一想,在广度优先搜索(BFS)的定义中,是不是也有这种层的思想出现呢?广度优先搜索对于一个节点来说,先访问它的所有子节点,然后再访问子节点的子节点(深度优先搜索是顺着根节点先访问完这一条路径上的所有节点,然后再去访问第二个子节点),这是不是出现了层?
广度优先搜索是通过队列实现的,下面同样给出一个普适的通过队列实现广度优先搜索的例子
queue<int> BFS; BFS.push(root); while (BFS.size() != 0) { BFS.push(BFS.front()->left); BFS.push(BFS.front()->right); // do something there BFS.pop(); }
同样的大家可以模拟一下代码执行的过程,对比深度优先搜索,这样能更好的理解队列、栈、广度优先搜索和深度优先搜索。
我们已经知道了怎样层次遍历,也就是说我们已经按层遍历二叉树了,但是要想解决问题还有两个困难之处
1. 如何判断哪个节点位于哪一层呢?
2. 如果子节点是空的话按层次遍历不就会少两个数吗?
大家可以自己思考一下,解决方案我会在代码中说明。
3.代码实现
先看完整的代码
vector<int> rightSideView(TreeNode* root) { queue<TreeNode* > BFS; vector<int> result; if (root == NULL) return result; int rightSide = 1; int null = 0; int index = 0; BFS.push(root); while (BFS.size() != 0) { index++; if (BFS.front()->left != NULL) { BFS.push(BFS.front()->left); } else { null++; } if (BFS.front()->right != NULL) { BFS.push(BFS.front()->right); } else { null++; } if (index == rightSide) { result.push(BFS.front()->val); rightSide = rightSide * 2 - null; null = 0; } BFS.pop(); } return result;}
- 对于二叉树,我们可以发现每一层节点数目都是上一层的两倍(每个根节点有两个子节点),所以我们可以用一个index来作为每个节点在每一层中的下标。
- 用null来记录每一层中null节点的数目
- 用rightSide记录每一层应该有多少节点(在删除空节点之后)。在没有空节点的时候,下一层的节点数应该是当前层节点数x2,我们知道当前层的节点数,double之后再减去下一层空节点的数目就是下一层应该有的节点数。
我们可以发现,每次当index == rightSide时,证明我们到了最右端,到了最右端之后,我们需要重置index和null(从第一个开始算,并且新的一层空节点数暂时为0),此时我们就需要更新新一层的节点数,从第三点分析我们可以得到rightSide = rightSide * 2 - null。
其中的逻辑关系大家可以自己画图分析一下,这样更有助于理解。
4.结束
解题并不是关键,但是理解栈和深度优先搜索、队列和广度优先搜索的关系很重要。
模拟程序运行的步骤对于理解这两种重要的搜索方式有很大帮助。
对于任何我没有写清楚的地方请在评论区留言。
- [LeetCode]二叉树层次遍历讲解与实例
- leetcode 二叉树安装层次进行遍历
- LeetCode基础--二叉树--层次遍历
- 二叉树层次遍历与链队列
- 二叉树的创建与层次遍历
- 二叉树层次遍历与递归释放
- 二叉树的层次构建与层次遍历
- 层次遍历二叉树
- 层次遍历二叉树
- 二叉树层次遍历
- 二叉树 层次遍历
- 二叉树层次遍历
- 层次遍历二叉树
- 二叉树层次遍历
- 层次遍历二叉树
- 二叉树层次遍历
- 二叉树层次遍历
- 层次遍历二叉树
- L1-004. 计算摄氏温度
- Quartz教程 第12课 Quartz的其它特性
- 理解Maven中的SNAPSHOT版本和正式版本
- 解决中文乱码问题
- booterStrap体验-首页改造-响应式导航栏(1)
- [LeetCode]二叉树层次遍历讲解与实例
- JavaScript深拷贝和浅拷贝
- 【安全牛学习笔记】Web开发中的涉及到的权限问题
- 绝对路径和相对路径,创建目录和删除
- 理解GCD中任务和队列执行的原理
- UVALive 5733|Iterated Difference|暴力
- 员工是公司最大的投资人
- Quartz快速入门指导
- 常用Mysql命令