前言
欢迎阅读小王同学的长篇连载文章之《每天学一道leetcode》。
如果您从前做过这道题目,可以从小王同学的文章里增强对该题目的记忆和印象,思考一下小王同学给出的思路和解法有没有优化的空间。
如果您从前没有做过这道题,不妨跟小王同学一起学习一下解题思路,以后面试的时候也许会有妙用。
如果您对互联网技术、算法知识、程序员个人发展感兴趣,欢迎关注小王同学,小王同学将会在该领域持续更新。
与此同时,如果您有任何建议或者想法,欢迎留言给小王。
题目分析
103题是leetcode中一道中等难度的题目,这道题目是二叉树的层次遍历的变形题。
小王同学曾经分析过二叉树的层次遍历这道题目,地址在每天学一道leetcode:102. 二叉树的层次遍历。
我们先来看一下这道题目。
这道题目和二叉树的层次遍历相似,需要我们将遍历的顺序变为“之字形”。
接下来我们看一下这道题目的思路。
解题思路
方法一
第一种方法是大家最容易想到的方法。
通过观察我们可以发现,锯齿遍历的过程中,偶数层的叶子顺序是逆序的,而奇数层叶子顺序是正序的。
这样我们可以在层次遍历的基础上对每一层的数组进行反转操作,就可以得到正确的答案。
这的确是一种简单粗暴的方法,但是会带来额外的时间复杂度的开销。
反转数组的时间复杂度是O(n),在这个过程中我们需要遍历所有偶数层的叶子结点。
因此,小王同学认为,这是一种美中不足的方案。
方法二
基于小王同学上述的分析,我们希望能得到一种不需要反转数组,而是直接让遍历偶数层过程中直接逆序遍历。
各位同学,还记得在层次遍历中使用的队列吗?
我们可以通过设置一个flag标志,用来区分遍历到奇数层还是偶数层。
当遍历到奇数层的时候,我们让树节点进入队列的顺序逆置。
而这个逆置的关键就在于将元素插入至数组的前面。
这么说比较抽象,我们来看一下代码。
示例代码
以下是小王同学以Java实现的代码,欢迎各位同学指点和批评。
在这里小王同学进行一些补充。
cnt记录的是队列中的元素个数,其对应的就是上一层的树结点个数。
flag是一个boolean变量,true代表顺序插入,false则代表逆序插入(插入到数组最前面)。
这里小王同学还要提醒一下,每一个while循环的结束代表了一层遍历的完成。
所以,在每个while循环结束前,需要更新flag变量,因为整个树的遍历顺序是“奇偶奇偶”的。
性能测试
以下是小王同学该份代码在leetcode中文网站上的测试。
时间复杂度为O(n),因为遍历了树的n个结点。
空间复杂度为O(n),因为队列最多存放了树的所有结点(特殊情况)。
最后
今天的分享就到这里了。
如果你对小王同学的内容感兴趣,动动小手指,给小王一个赞鼓励一下吧。