【LeetCode】103. Binary Tree Zigzag Level Order Traversal 解题报告
2016-05-28 12:04
609 查看
转载请注明出处:/article/11841693.html
Given a binary tree, return the zigzag level order traversal of its nodes’ values. (ie, from left to right, then right to left for the next level and alternate between).
For example:
Given binary tree {3,9,20,#,#,15,7},
return its zigzag level order traversal as:
【LeetCode】102. Binary Tree Level Order Traversal 解题报告 是从顶层往下,从左往右的次序 遍历结点。
【LeetCode】107. Binary Tree Level Order Traversal II 解题报告 是从底层向上,从左往右的次序 遍历结点。
而该题目的意思是从顶层向下,”之字形” 顺序输出结点。(第一层从左向右,第二层从右向左,第三层从左向右……依次类推)。
主要就是记录当前结点所在的层级,或者当前层的结点的个数。
遇到需要反向的层的时候,调用Collections.reverse()方法或者使用LinkedList的addFirst()方法,还可以使用ArrayList的add(0, E)方法 (该方法效率不高,需要拷贝数组)。
将【102】题目中的递归方法 进行改造。
因为有层级这个变量,所以需要在每次递归时,判断 level % 2 是否为0 即可。
该方法效率最高
LeetCode 平台 Run Time 是 1ms
beats 96.02 % of java submissions.
说明可以通过栈的方式来做。
两个栈,一个从左向右遍历的层,一个存储从右向左遍历的层。
从该题目的【Discuss】中看到一种使用Deque – 双端队列的解法。
它的思想就是:
flag是true的时候,将节点从左向右添加到队尾。这样从队尾pollLast()的时候,顺序就是从右向左;
flag是false的时候,将节点从右向左添加到对头,这样从对头pollFirst()的时候,顺序就是从左向右。
【102】【107】【103】这些题目大体都是类似的。都是层序遍历输出二叉树。只不过顺序有差别而已。
大家可以举一反三。可以想想怎么从底层向上之字形层序遍历二叉树。
bingo~~
Subject
出处:https://leetcode.com/problems/binary-tree-zigzag-level-order-traversal/Given a binary tree, return the zigzag level order traversal of its nodes’ values. (ie, from left to right, then right to left for the next level and alternate between).
For example:
Given binary tree {3,9,20,#,#,15,7},
3 / \ 9 20 / \ 15 7
return its zigzag level order traversal as:
[ [3], [20,9], [15,7] ]
Explain
该题目与之前两题非常相似。【LeetCode】102. Binary Tree Level Order Traversal 解题报告 是从顶层往下,从左往右的次序 遍历结点。
【LeetCode】107. Binary Tree Level Order Traversal II 解题报告 是从底层向上,从左往右的次序 遍历结点。
而该题目的意思是从顶层向下,”之字形” 顺序输出结点。(第一层从左向右,第二层从右向左,第三层从左向右……依次类推)。
Solution
solution 1
第一种方案使用【102】题目中的非递归方法 进行修改。主要就是记录当前结点所在的层级,或者当前层的结点的个数。
遇到需要反向的层的时候,调用Collections.reverse()方法或者使用LinkedList的addFirst()方法,还可以使用ArrayList的add(0, E)方法 (该方法效率不高,需要拷贝数组)。
/** * 3ms <br /> * * beats 14.87% of java submissions * * @author jacksen * @param root * @return */ public List<List<Integer>> zigzagLevelOrder(TreeNode root) { List<List<Integer>> result = new ArrayList<List<Integer>>(); if (root == null) { return result; } Queue<TreeNode> queue = new LinkedList<TreeNode>(); queue.add(root); int i = queue.size(); // 记录每层的结点个数 boolean flag = false; TreeNode tempNode = null; List<Integer> singleLevel = new ArrayList<>(); while (!queue.isEmpty()) { if (i == 0) {// 一层记录结束 // if (flag) { Collections.reverse(singleLevel); } result.add(singleLevel); // flag = !flag; i = queue.size(); singleLevel = new ArrayList<>(); } tempNode = queue.poll(); singleLevel.add(tempNode.val); --i; if (tempNode.left != null) { queue.add(tempNode.left); } if (tempNode.right != null) { queue.add(tempNode.right); } } if (flag) { Collections.reverse(singleLevel); } result.add(singleLevel); return result; }
/** * 2ms <br /> * * beats 60.36% of java submissions * * @author jacksen * @param root * @return */ public List<List<Integer>> zigzagLevelOrder5(TreeNode root) { List<List<Integer>> result = new ArrayList<List<Integer>>(); if (root == null) { return result; } Queue<TreeNode> queue = new LinkedList<TreeNode>(); queue.add(root); int i = queue.size(); // 记录每层的结点个数 boolean flag = true; TreeNode tempNode = null; LinkedList<Integer> singleLevel = new LinkedList<>(); while (!queue.isEmpty()) { if (i == 0) {// 一层记录结束 // result.add(singleLevel); // i = queue.size(); singleLevel = new LinkedList<>(); flag = !flag; } tempNode = queue.poll(); if (flag) { singleLevel.add(tempNode.val); } else { singleLevel.addFirst(tempNode.val); } --i; if (tempNode.left != null) { queue.offer(tempNode.left); } if (tempNode.right != null) { queue.offer(tempNode.right); } } result.add(singleLevel); return result; }
solution 2
通过递归方式。将【102】题目中的递归方法 进行改造。
因为有层级这个变量,所以需要在每次递归时,判断 level % 2 是否为0 即可。
/** * 递归方式 <br /> * 重要的是记录层级, 加上一个标识标识是否集合反向<br /> * * 1ms<br /> * eats96.02% of java submissions * * @author jacksen * @param root * @return */ public List<List<Integer>> zigzagLevelOrder2(TreeNode root) { List<List<Integer>> result = new ArrayList<List<Integer>>(); // levelRecursion(root, result, 0, false); levelRecursion2(root, result, 0); return result; }
/** * 递归方法 */ private void levelRecursion(TreeNode node, List<List<Integer>> result, int level, boolean flag) { if (node == null) { return; } if (result.size() < level + 1) {// 说明还需要添加一行 result.add(new LinkedList<Integer>()); } if (flag) { ((LinkedList<Integer>) result.get(level)).addFirst(node.val); } else { result.get(level).add(node.val); } levelRecursion(node.left, result, level + 1, !flag); levelRecursion(node.right, result, level + 1, !flag); } /** * 可以直接通过level层级判断是否需要addFirst,不必要再添加额外的标识 * * @param node * @param result * @param level */ private void levelRecursion2(TreeNode node, List<List<Integer>> result, int level) { if (node == null) { return; } if (result.size() < level + 1) {// 说明还需要添加一行 result.add(new LinkedList<Integer>()); } if (level % 2 != 0) { ((LinkedList<Integer>) result.get(level)).addFirst(node.val); } else { result.get(level).add(node.val); } levelRecursion2(node.left, result, level + 1); levelRecursion2(node.right, result, level + 1); }
该方法效率最高
LeetCode 平台 Run Time 是 1ms
beats 96.02 % of java submissions.
solution 3
该题目的Tags 显示了一个“Stack”标签。说明可以通过栈的方式来做。
/** * 用两个栈的方式 <br /> * 3ms <br /> * beats 14.87% of java submissions * * @author jacksen * @param node * @return */ public List<List<Integer>> zigzagLevelOrder3(TreeNode root) { List<List<Integer>> result = new ArrayList<List<Integer>>(); if (root == null) { return result; } Stack<TreeNode> forwardStack = new Stack<>(); Stack<TreeNode> retrorseStack = new Stack<>(); forwardStack.push(root); TreeNode tempNode = null; List<Integer> singleList = new ArrayList<>(); while (!forwardStack.isEmpty() || !retrorseStack.isEmpty()) { while (!forwardStack.isEmpty()) { tempNode = forwardStack.pop(); singleList.add(tempNode.val); if (tempNode.left != null) { retrorseStack.push(tempNode.left); } if (tempNode.right != null) { retrorseStack.push(tempNode.right); } } if (!singleList.isEmpty()) { result.add(singleList); singleList = new ArrayList<>(); } while (!retrorseStack.isEmpty()) { tempNode = retrorseStack.pop(); singleList.add(tempNode.val); if (tempNode.right != null) { forwardStack.push(tempNode.right); } if (tempNode.left != null) { forwardStack.push(tempNode.left); } } if (!singleList.isEmpty()) { result.add(singleList); singleList = new ArrayList<>(); } } return result; }
两个栈,一个从左向右遍历的层,一个存储从右向左遍历的层。
solution 4
之字形层序输出,主要就是上一层从左向右,下一层从右向左。故而需要一个标志来进行区分。从该题目的【Discuss】中看到一种使用Deque – 双端队列的解法。
/** * deque <b>双端队列</b> <br /> * 3ms <br/> * beats 14.87% of java submissions * * @author https://leetcode.com/discuss/89116/java-bfs-with-deque * * @param root * @return */ public List<List<Integer>> zigzagLevelOrder4(TreeNode root) { List<List<Integer>> result = new ArrayList<List<Integer>>(); if (root == null) { return result; } boolean flag = true; TreeNode tempNode = null; TreeNode lastNode = root; List<Integer> singleLevel = new ArrayList<>(); Deque<TreeNode> deque = new LinkedList<>(); deque.offer(root); while (!deque.isEmpty()) { tempNode = flag ? deque.pollFirst() : deque.pollLast(); singleLevel.add(tempNode.val); if (flag) {// left->right顺序添加到对尾 if (tempNode.left != null) { deque.offerLast(tempNode.left); } if (tempNode.right != null) { deque.offerLast(tempNode.right); } } else { if (tempNode.right != null) { deque.offerFirst(tempNode.right); } if (tempNode.left != null) { deque.offerFirst(tempNode.left); } } if (tempNode == lastNode) { result.add(singleLevel);// 搞定一层 singleLevel = new ArrayList<>(); lastNode = flag ? deque.peekFirst() : deque.peekLast(); flag = !flag; } } return result; }
它的思想就是:
flag是true的时候,将节点从左向右添加到队尾。这样从队尾pollLast()的时候,顺序就是从右向左;
flag是false的时候,将节点从右向左添加到对头,这样从对头pollFirst()的时候,顺序就是从左向右。
【102】【107】【103】这些题目大体都是类似的。都是层序遍历输出二叉树。只不过顺序有差别而已。
大家可以举一反三。可以想想怎么从底层向上之字形层序遍历二叉树。
bingo~~
相关文章推荐
- Hibernate包及相关工具包下载地址
- Android进阶专题九:电池续航
- poj 1860 汇率2
- tomcat常见错误及解决方案
- SSH输入错误Action
- Android SlidingMenu 使用
- Android中的事件分发
- iOS开发之手势识别汇总
- 【持续更新中……】好玩的网站
- symfony 使用原始sql
- new Option及用法
- 微视图像(microview)gige相机开发手记(1)
- php函数的创建,以及引用传递和值传递的介绍!
- 使用IDEA开发Spark应用
- Android进阶专题八:性能评估
- Caffe学习(3):训练自己的数据
- github服务器挂了
- 直接双击启动tomcat中的startup.bat闪退原因及解决方法
- java字符串的判断
- 1022. D进制的A+B (20)