我编写了一个代码,用于在二叉树中查找具有最大元素总和的级别。我有几个问题。
可以有更好的设计吗?
public class MaxSumLevel {
public static int findLevel(BinaryTreeNode root) {
Queue mainQ = new Queue();
Queue tempQ = new Queue();
int maxlevel = 0;
int maxVal = 0;
int tempSum = 0;
int tempLevel = 0;
if (root != null) {
mainQ.enqueue(root);
maxlevel = 1;
tempLevel = 1;
maxVal = root.getData();
}
while ( !mainQ.isEmpty()) {
BinaryTreeNode head = (BinaryTreeNode) mainQ.dequeue();
BinaryTreeNode left = head.getLeft();
BinaryTreeNode right = head.getRight();
if (left != null) {
tempQ.enqueue(left);
tempSum = tempSum + left.getData();
}
if (right != null) {
tempQ.enqueue(right);
tempSum = tempSum + right.getData();
}
if (mainQ.isEmpty()) {
mainQ = tempQ;
tempQ = new Queue();
tempLevel ++;
if (tempSum > maxVal) {
maxVal = tempSum;
maxlevel = tempLevel;
tempSum = 0;
}
}
}
return maxlevel;
}
}
答案 0 :(得分:1)
这取决于您的树木有多少节点以及它们有多深。由于您正在执行breadth first search,因此您的队列将占用 O(n)内存空间,这对大多数应用程序都是可以的。
以下解决方案具有 O(l)空间复杂度和 O(n)时间复杂度( l 是树的深度和 n 其顶点数量):
public List<Integer> levelsSum(BinaryTreeNode tree) {
List<Integer> sums = new ArrayList<Integer>()
levelsSum(tree, sums, 0);
return sums;
}
protected void levelsSum(BinaryTreeNode tree, List<Integer> levelSums, int level) {
if (tree == null)
return;
// add new element into the list if needed
if (level.size() <= level)
levelSums.add(Integer.valueOf(0));
// add this node's value to the appropriate level
levelSums.set(level, levelSums.get(level) + tree.getData());
// process subtrees
levelSum(tree.getLeft(), levelSums, level + 1);
levelSum(tree.getRight(), levelSums, level + 1);
}
现在只需在树上调用levelsSum
并扫描返回的列表以找到最大值。
答案 1 :(得分:1)
我喜欢递归(注意,未经测试的代码):
public static int maxLevel(BinaryTreeNode tree) {
ArrayList<Integer> levels = new ArrayList<Integer>();
findLevels(tree, 0, levels);
// now just return the index in levels with the maximal value.
// bearing in mind that levels could be empty.
}
private static void findLevels(BinaryTreeNode tree, int level,
ArrayList<Integer> levels) {
if (tree == null) {
return;
}
if (levels.length <= level) {
levels.add(0);
}
levels.set(level, levels.get(level) + tree.getData());
findLevels(tree.getLeft(), level+1, levels);
findLevels(tree.getRight(), level+1, levels);
}
如果我对垃圾收集器真的很有意义,我会让findLevels返回一个(级别,值)对的列表并对它们求和。这在共同规范的语言中更有意义,但在Java中它会很奇怪。
显然,您可以在递归函数中使用策略,并使用要处理的显式堆栈节点来执行此操作。我和你的方式之间的关键区别在于我的记忆与树的高度成正比;你的内存与其宽度成正比。
查看您的代码,这种方法似乎很合理。我将tempLevel
重命名为currentLevel
,我倾向于将内循环拉入函数sumLevel
,该函数接受队列并返回一个int和一个队列(实际上除外)队列是一个参数,因为你只能返回一个值,grrr)。但它似乎没问题。
答案 2 :(得分:0)
你确定元素都是非负面的吗?
我会像new MaxSumLevel(root).getLevel()
一样调用它。否则,当你有时必须返回maxSum时,你会怎么做?
我会将其构造为2个嵌套循环:
while(!mainQ.isEmpty()){
while(!mainQ.isEmpty()){
BinaryTreeNode head = (BinaryTreeNode) mainQ.dequeue();
BinaryTreeNode left = head.getLeft();
BinaryTreeNode right = head.getRight();
if (left != null) {
tempQ.enqueue(left);
tempSum = tempSum + left.getData();
}
if (right != null) {
tempQ.enqueue(right);
tempSum = tempSum + right.getData();
}
}
mainQ = tempQ;
tempQ = new Queue();
tempLevel ++;
if (tempSum > maxVal) {
maxVal = tempSum;
maxlevel = tempLevel;
tempSum = 0;
}
}
答案 3 :(得分:0)
这种递归方法对我有用:
public int findMaxSumRootLeaf(TreeNode node,int currSum) {
if(node == null)
return 0;
return Math.max(findMaxSumRootLeaf(node.leftChild,currSum)+node.data, findMaxSumRootLeaf(node.rightChild,currSum)+node.data);
}
答案 4 :(得分:0)
您可以使用队列中的null
来表示级别的结束,并计算每个级别的最大总和。
public int maxLevelSum(BinaryTreeNode root) {
if (root == null) //if empty tree
return 0;
else {
int current_sum = 0;
int max_sum = 0;
Queue<BinaryTreeNode> queue = new LinkedList<BinaryTreeNode>(); //initialize a queue
queue.offer(root); //add root in queue
queue.offer(null); // null in queue represent end of a level
while (!queue.isEmpty()) {
BinaryTreeNode temp = queue.poll();
if (temp != null) {
if (temp.getLeft() != null) //if left is not null
queue.offer(temp.getLeft());
if (temp.getRight() != null)
queue.offer(temp.getRight()); //if right is not null
current_sum = current_sum + temp.getData(); //add to level current level sum
} else { // we reached end of a level
if (current_sum > max_sum) //check if cuurent level sum is greater than max
max_sum = current_sum;
current_sum = 0; //make current_sum=0 for new level
if (!queue.isEmpty())
queue.offer(null); //completion of a level
}
}
return max_sum; //return the max sum
}
}