BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / acm-icpc / #93892同步于 2017/9/1
该镜像源已超过 30 天没有更新,可能在源站已被删除。
ACM_ICPC机器人发帖

LeetCode662 Maximum Width of Binary Tree

BILL
2017/9/1镜像同步28 回复
[b]lz最近在做这题,这题的题意很明确,就是求一棵二叉树的最大宽度。但是这个宽度是指同一行中开头和结尾的两个节点之间的距离,包括空节点。 我的方法比较繁琐,首先求树高,然后按照树高,对每一层进行层次遍历,将每一层的值存入一个arraylist中,包括空值,其实就是存入了一棵完全二叉树,然后遍历完一层后,都计算下相应的这一层中的宽度,以此类推,直到每一层都遍历完,那么就得到了这棵二叉树的最大宽度。但是我写的代码在leetcode中运行,出现了超时的问题,求哪位大神帮lz看看代码,希望不要改变我的思路,谢谢!代码如下: public class widthOfBinaryTree { public int widthOfBinaryTree(TreeNode root) { if(root == null) return 0; int height = getDepth(root); Queue<TreeNode> queue = new LinkedList<>(); //队列用来对二叉树进行层次遍历 queue.add(root); int max = 1; for(int i = 0; i < height - 1; i++) { ArrayList<String> list = new ArrayList<>(); //对每一层的所有节点,包括空节点都保存进arraylist中,用于计算每一层的最大宽度 int curr = 0; int length = queue.size(); for(int j = 0; j < length; j++) { TreeNode node = queue.poll(); if(node == null) //如果遇到此节点是空的,那么其左孩子和右孩子也必定是空的,那么就将相应的空节点保存进arraylist中 { queue.add(null); queue.add(null); list.add(" "); list.add(" "); } else if(node != null) { if(node.left != null) { queue.add(node.left); list.add(String.valueOf(node.left.val)); } else if(node.left == null) { queue.add(null); list.add(" "); } if(node.right != null) { queue.add(node.right); list.add(String.valueOf(node.right.val)); } else if(node.right == null) { queue.add(null); list.add(" "); } } } int start = 0; int end = list.size() - 1; while(start < end) //对一层遍历完后,来求其最大宽度,用start和end来限定 { if(list.get(start) == " ") { start = start + 1; } if(list.get(end) == " ") { end = end - 1; } if(list.get(start) != " " && list.get(end) != " ") break; } curr = end - start + 1; max = max > curr ? max : curr; } return max; } public int getDepth(TreeNode root) //求树高 { if(root == null) return 0; int left = getDepth(root.left); int right = getDepth(root.right); return 1 + Math.max(left,right); } }
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
NachtZ机器人#1 · 2017/9/1
首先,你拿到层高的意义是什么?你既然是bfs了。一层一层的扫,当前层是什么高度,对你来说不重要的。所以你不需要先拿到depth,完全可以直接扫。其次,你为什么要保存中间的值?有什么意义么?你只是要的是当前节点在这一层的index而已。又不是要把整个树的值都过一遍。所以你的queue完全可以换成一个begin和一个end。然后就不需要再首尾去掉空字符这么麻烦了,还省去了入队,int换string,遍历队列的时间,而且你去掉首尾空字符的方法也很慢,用二分去找快点,你还要再来一个复杂度为o(n)的过滤方式。
xlrainy机器人#2 · 2017/9/1
在层序遍历的while里加一句 int curentWidth = queue.size(); 然后for 1:currentWidth queue.dequeue(); 取currentWidth最大值即可 来自 缘邮
BILL机器人#3 · 2017/9/2
额,可是这个队列有保存空节点,如果只取最大的节点,并不能直接用于计算其最大宽度?不是特别明白你的思路,能再说得详细点吗?谢谢 【 在 xlrainy 的大作中提到: 】 : 在层序遍历的while里加一句 : int curentWidth = queue.size(); : 然后for 1:currentWidth :
BILL机器人#4 · 2017/9/2
大神,感觉你说得很对,但还不是特别理解,能否直接在我上面的代码上改写新代码,谢谢! 【 在 NachtZ 的大作中提到: 】 : 首先,你拿到层高的意义是什么?你既然是bfs了。一层一层的扫,当前层是什么高度,对你来说不重要的。所以你不需要先拿到depth,完全可以直接扫。其次,你
NachtZ机器人#5 · 2017/9/2
你这,要我改你刷题有啥意义?你还不如去discuss区抄答案。 【 在 BILL 的大作中提到: 】 : 大神,感觉你说得很对,但还不是特别理解,能否直接在我上面的代码上改写新代码,谢谢!
wthwth机器人#6 · 2017/9/2
看到这题就好熟悉啊,dicuss第三个答案是我post的,大家看到了可以给我点个赞。
wthwth机器人#7 · 2017/9/2
哦 粗略看了下明白你的意思了 主要是当树形成单链表可能会超时吧,你这方法好像计算高度是有必要的。主要是在找start和end可以用二分查找去优化吧。 【 在 BILL 的大作中提到: 】 : 大神,感觉你说得很对,但还不是特别理解,能否直接在我上面的代码上改写新代码,谢谢!
www210294机器人#8 · 2017/9/2
按层遍历,每一层的每个节点包括所有null节点都放到一个arraylist里面,每层遍历完再处理一下,把arraylist里面的头尾的空节点去掉,记录arraylist最大值即可’
YZJLOVECHEER机器人#9 · 2017/9/2
稍微改了下。。104/108 超过了内存限制,lz还是换种思路吧 public int widthOfBinaryTree(TreeNode root) { if(root == null) return 0; Queue<TreeNode> queue = new LinkedList<>(); //队列用来对二叉树进行层次遍历 queue.add(root); int max = 1; boolean flag = true; while (!queue.isEmpty() && flag) { flag = false; ArrayList<String> list = new ArrayList<>(); //对每一层的所有节点,包括空节点都保存进arraylist中,用于计算每一层的最大宽度 int curr = 0; int length = queue.size(); for(int j = 0; j < length; j++) { TreeNode node = queue.poll(); if(node == null) //如果遇到此节点是空的,那么其左孩子和右孩子也必定是空的,那么就将相应的空节点保存进arraylist中 { queue.add(null); queue.add(null); list.add(" "); list.add(" "); } else if(node != null) { if(node.left != null) { queue.add(node.left); list.add(String.valueOf(node.left.val)); flag = true; } else if(node.left == null) { queue.add(null); list.add(" "); } if(node.right != null) { queue.add(node.right); list.add(String.valueOf(node.right.val)); flag = true; } else if(node.right == null) { queue.add(null); list.add(" "); } } } int start = 0; int end = list.size() - 1; while (start < end && list.get(start).equals(" ")) { start++; } while (start < end && list.get(end).equals(" ")) { end--; } // while(start < end) //对一层遍历完后,来求其最大宽度,用start和end来限定 // { // if(list.get(start) == " ") // { // start = start + 1; // } // if(list.get(end) == " ") // { // end = end - 1; // } // if(list.get(start) != " " && list.get(end) != " ") // break; // } curr = end - start + 1; max = max > curr ? max : curr; } return max; } 还有比较字符串最好用.equals()?