算法面试题:逆时针打印二叉树外围边缘
来源:互联网 发布:初中网络教育 编辑:程序博客网 时间:2024/05/19 17:49
更详细的讲解和代码调试演示过程,请参看视频
用java开发C语言编译器
更详细的讲解和代码调试演示过程,请参看视频
如何进入google,算法面试技能全面提升指南
如果你对机器学习感兴趣,请参看一下链接:
机器学习:神经网络导论
更详细的讲解和代码调试演示过程,请参看视频
Linux kernel Hacker, 从零构建自己的内核
给定一颗二叉树如下:
要求把二叉树的外边缘按照逆时针的方式打印出来,也就是你需要打印出以下节点:
314, 6, 271, 28, 0, 17, 641, 257, 29 ,278, 7
整个二叉树的外边缘分三部分,第一部分是最左边缘,也就是节点314, 6, 271, 28。第二部分是底边节点,他们分别是0, 17, 641, 257, 29。第三部分是右边缘,他们分别是7, 278.
左边缘的节点从根节点开始,一直访问左孩子,直到左孩子为空;
底部节点实际上是二叉树的所以叶子节点;
右边缘节点是从根节点开始,一直访问右节点,直到右孩子为空;
根据以上三种情况,通过遍历二叉树,获得三种性质的节点,把他们组合起来就是二叉树的逆时针外边缘了。由此代码实现如下:
import java.util.ArrayList;import java.util.Stack;public class AntiClockWiseTravel { private ArrayList<TreeNode> antiClockWiseNodeList = new ArrayList<TreeNode>(); private TreeNode root; private void getLeftSizeNodes() { TreeNode node = root; while (node != null) { antiClockWiseNodeList.add(node); node = node.left; } } private void inorder(TreeNode node) { if (node == null) { return; } inorder(node.left); if (node.left == null && node.right == null) { if (antiClockWiseNodeList.get(antiClockWiseNodeList.size() - 1) != node) { antiClockWiseNodeList.add(node); } return; } inorder(node.right); } private void getBottomSizeNodes() { TreeNode node = root; inorder(node); } private void getRightSizeNodes() { TreeNode node = root; Stack<TreeNode> stack = new Stack<TreeNode>(); node = node.right; while (node != null) { stack.push(node); node = node.right; } while (stack.empty() != true) { TreeNode n = stack.pop(); if (antiClockWiseNodeList.get(antiClockWiseNodeList.size() - 1 ) != n) { antiClockWiseNodeList.add(n); } } } public AntiClockWiseTravel(TreeNode root) { this.root = root; getLeftSizeNodes(); getBottomSizeNodes(); getRightSizeNodes(); } public ArrayList<TreeNode> getAntiClockWiseNodes() { return antiClockWiseNodeList; }}
antiClockWiseNodeList是一个二叉树节点队列,专门用来存储二叉树外边缘的节点,首先我们通过getLeftSizeNodes来获取左边缘的几点,它实现方法简单,只是从跟节点开始,始终访问左孩子,并把他们加入队列。
getBottomSizeNodes用来获得边缘的底部节点,它使用中序遍历二叉树节点,每遍历一个节点就判断其是否是叶子节点,如果是,则把它加入队列,这里要注意的是,底部节点与左边缘节点有可能会发送重复,例如节点28既是左边缘节点,也是底部节点,因此加入的时候要做个判断,代码中的if判断,作用就是防止把左边缘和底部边缘的重合节点加入队列两次。
函数getRightSizeNodes目的是获得右边缘节点,这里需要注意的是,当我们从根节点开始,依次访问右孩子时,所得节点的次序是顺时针的,例如从根节点开始访问右边缘节点是,节点次序是7, 278, 29, 但我们需要的是逆时针次序,也就是说,我们想要的节点次序是29, 278, 7,所以在代码实现中,使用了一个小技巧,当获得右边缘节点时,先将他们压入堆栈,因为堆栈的特点是后进先出,压入堆栈后再把堆栈中的节点依次弹出,这样的话我们得到的节点次序就是逆时针的了。这里还需要注意的一点是,右边缘节点和底部节点有重复节点,例如节点29就是他们的重复节点,代码中的if判断就是为了防止把重复节点添加两次。
我们再看看主入口代码:
import java.util.ArrayList;public class BinaryTree { public static void main(String[] s) { int[] inorder = new int[]{28, 271, 0, 6, 561, 17, 3, 314, 2, 401, 641, 1, 257, 7, 278, 29}; int[] preorder= new int[] {314, 6, 271, 28, 0, 561, 3, 17, 7, 2, 1, 401, 641, 257, 278, 29}; BTreeBuilder treeBuilder = new BTreeBuilder(inorder, preorder); TreeNode root = treeBuilder.getTreeRoot(); PrintTreeList pt = new PrintTreeList(root); pt.printTree(); System.out.print("\n"); AntiClockWiseTravel at = new AntiClockWiseTravel(root); ArrayList<TreeNode> list = at.getAntiClockWiseNodes(); for (int i = 0; i < list.size(); i++) { TreeNode n = list.get(i); System.out.print(n.val + " "); } }}
首先我们给定二叉树的中序遍历节点和前序遍历节点,上一节我们给出了如何根据两种节点次序构建二叉树的算法,构建出给定的二叉树后,把二叉树的根节点传递给AntiClockWiseTravel,通过该类获得一个节点队列,这个节点队列包含了二叉树以逆时针次序存放的外部边缘节点,上面的代码运行后得到结果如下:
314 6 271 28 0 17 641 257 29 278 7
由此可见,我们的算法准确的以逆时针方式打印了二叉树的外部边缘节点。
更多技术信息,包括操作系统,编译器,面试算法,机器学习,人工智能,请关照我的公众号:
- 算法面试题:逆时针打印二叉树外围边缘
- 面试题 23: 从上到下打印二叉树
- 面试题23:从上到下打印二叉树
- 【二叉树】按逆时针顺序打印树的外层节点
- 面试题22:从上往下打印二叉树
- 面试题21:从上往下打印二叉树
- 面试题23:从上往下打印二叉树
- 【面试题二十三】从上往下打印二叉树
- 从上往下打印二叉树(面试题 23)
- 面试题23 从上往下打印二叉树
- 面试题23:从上往下打印二叉树
- 《剑指Offer》面试题23:从上到下打印二叉树
- 面试题60:把二叉树打印成多行
- 面试题61:按之字形顺序打印二叉树
- 面试题23:从上往下打印二叉树
- 面试题23从上往下打印二叉树
- 面试题23_从上往下打印二叉树
- (面试题23)从上打印二叉树
- ES01--CURL认知
- linux下网络运行监控软件iptraf&&clamav
- (转)星巴克其实是靠大数据盈利的!
- Spring框架的设计理念与设计模式分析
- Java回炉重造(七)使用Apache Commons Math创建向量
- 算法面试题:逆时针打印二叉树外围边缘
- C#——主进程负责向屏幕不间断输出四位随机数,子线程负责每隔 1 秒钟对当前计算机屏幕进行截屏并以 jpg 格式的图片保存文件。
- ES02--索引mapping的写入、查看与修改
- webstorm入门5-sass、scss、less监听编译
- MySql函数应用,分组排序,子查询学习笔记
- day11 eclise使用
- 逃跑按钮
- 多线程实现电梯程序——Map+Queue
- Oracle的子查询和集合运算