面试官:下面我们写些算法题吧
小猫: 好的
面试官:你实现一下,层序输出二叉树
小猫:好的,刷刷刷写出来了。
面试官:嗯.... 可以。你再写一个,层序输出并且输出行号。
小猫内心:层序输出,并且输出行号,我平常学的时候,只学过层序输出....,哎呀,紧张......
这个那个...... 最后挂了......
小猫回去的路上镇定下来了,输出行号..... 好多种实现方式呢,我怎么当时脑子一片空白....哎呀,还是太紧张了.... 以后一定要学会镇定呀,不然自己有思路也想不出来。。
你有没有因为紧张而影响发挥过呢?另外小猫意识到,知识扩展和迁移能力非常重要。遇到生题一定不能紧张,要根据现有的知识进行思考,也许就思考出答案了。
回家后小猫把自己想的几种方式整理一下,兴许下次面试能够用到。
01 题目
给你一颗二叉树,层序输出二叉树,并输出行号。
如
输出结果如下:
第一行:0
第二行:1,2
第三行:3, 4,5,6
第四行:7
02 解题
在此说明解法不唯一,如果有其他更好想法,欢迎一起交流。
我们在层序输出二叉树的时候,会用队列完成,如果有不会的可以看上篇文章的解释
层序输出二叉树动态图解,那么如何输出行号呢,如何确定这一行已经结束了呢。
既然要一行一行输出,我可以把每行元素放在一个队列里面,用行号标记这个队列。那么
即Map map结构刚好能够实现这个思路。nice!
接下来,我们用图详细解释
0.初始化LineNumber=0,Map 对应key=LineNumber,value=queue[0]
1.map获取LineNumber=0的队列queue=[0] ,弹出队首元素,并输出。
把0的左右孩子节点1,2,放入key=lineNumber+1 第1行的队列中
由于LineNumber=0第0行的队列为空,说明这一行已经全部输出,删除map中空队列,并且行号加一LineNumber++ LineNumber=1
2.获取LineNumber=1,的队首元素1,输出
将1的左右孩子节点,3,4放入下一行的队列中
继续弹出第1行元素2,并且输出
将2对应的左右孩子节点放入LineNumber+1对应的队列中
此时LineNumber=1对应的队列为空,说明此行已经输出完毕,删除map中的该队列,换行LIneNumber++
接下来重复上述步骤,直到map为空结束。
03 总结
Map初始化 LineNumber=0,queue=[0]
- 通过LineNumber 获取队列中队首的节点,输出。
- 将输出节点对应的左右孩子节点放入map.Key=LineNumber+1的队列中。
- 判断LineNumber对应的本行是否为空,如果为空,则说明本行结束,删除该行对应的队列。并且换行LineNumber++
- map为空,则结束
04 代码实现
import java.util.Queue;import java.util.HashMap;import java.util.Map;import java.util.concurrent.LinkedBlockingQueue;public class 面试题23层序打印二叉树进阶 { /** * 层序打印二叉树并输出行号 */ public static void printBinaryTree(BinaryTreeNode binaryTree) { if (binaryTree == null) { return; } // 1.一个总的map Map> treeNodeMap = new HashMap<>(); // 2.root节点队列 int levelNumber = 0; Queue binaryTreeNodes = new LinkedBlockingQueue<>(); binaryTreeNodes.add(binaryTree); treeNodeMap.put(levelNumber, binaryTreeNodes); // 输出第一行行号 System.out.print("第" + levelNumber + "行"); while (!treeNodeMap.isEmpty()) { // 3. 读取当前行 Queue curLineQueue = treeNodeMap.get(levelNumber); // 4.读取当前行队首元素 BinaryTreeNode tmpNode = curLineQueue.remove(); // 输出 System.out.print(" " + tmpNode.value + " "); // 5.下一行数值,读取队列,或者初始化队列 Queue nextLineQueue = treeNodeMap.getOrDefault(levelNumber + 1, new LinkedBlockingQueue<>()); if (tmpNode.leftChild != null) { // 不为空,王下一行队列里加 nextLineQueue.add(tmpNode.leftChild); } if (tmpNode.rightChild != null) {// 不为空,王下一行队列里加 nextLineQueue.add(tmpNode.rightChild); } if (nextLineQueue.size() > 0) {// 如果不为空,重新put以下,防止对于初始化的队列,没有在map里面 treeNodeMap.put(levelNumber + 1, nextLineQueue); } //5.当前行输出完毕的话,删除当前行map key,value,行号++ if (curLineQueue.size() <= 0) {// 当前行已经输出完毕 treeNodeMap.remove(levelNumber); levelNumber ++; } // 6. 当前行已经结束,但是不是最后一行输出行号 if (curLineQueue.size() <= 0 && !treeNodeMap.isEmpty()) { System.out.println(); System.out.print("第" + levelNumber + "行"); } } } public static void main(String[] args) { BinaryTreeNode treeNode7 = new BinaryTreeNode(null, null, 7); BinaryTreeNode treeNode6 = new BinaryTreeNode(null, null, 6); BinaryTreeNode treeNode5 = new BinaryTreeNode(treeNode7, null, 5); BinaryTreeNode treeNode4 = new BinaryTreeNode(null, null, 4); BinaryTreeNode treeNode3 = new BinaryTreeNode(null, null, 3); BinaryTreeNode treeNode2 = new BinaryTreeNode(treeNode5, treeNode6, 2); BinaryTreeNode treeNode1 = new BinaryTreeNode(treeNode3, treeNode4, 1); BinaryTreeNode treeNode = new BinaryTreeNode(treeNode1, treeNode2, 0); printBinaryTree(treeNode); }}