【问题标题】:Binary Tree Max sum level - Better Design?二叉树最大总和水平 - 更好的设计?
【发布时间】:2012-08-13 06:55:32
【问题描述】:

我编写了一个代码,用于在具有最大元素总和的二叉树中查找级别。我有几个问题。

  1. 这是一个好的设计吗? - 我使用了 2 个队列,但两个队列存储的元素总数将小于 n。所以我认为应该没问题。
  2. 还有更好的设计吗?

    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;
    }
    

    }

【问题讨论】:

  • 更适合CodeReview.SE
  • @Amit,看起来代码审查的用户群非常低。也确实在这里讨论了这种 Q。所以我觉得这个论坛更合适

标签: java algorithm optimization tree binary-tree


【解决方案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 返回一个 (level, value) 对的列表,然后对它们求和。这在协同程序类型的语言中更有意义,但在 java 中会很奇怪。

显然,您可以在递归函数中采用策略,并使用要处理的显式节点堆栈来执行此操作。我的方式和你的方式之间的主要区别在于我的方式与树的高度成正比。你的占用内存与其宽度成正比。

查看您的代码,这种方法似乎很合理。我将tempLevel 重命名为currentLevel,并且我倾向于将内部循环拉出到一个函数sumLevel 中,该函数接受一个队列并返回一个int 和一个队列(实际上队列将是一个参数, 因为你只能返回一个值,grrr)。但它看起来还不错。

【讨论】:

    【解决方案2】:

    这取决于你的树有多少节点以及它们有多深。由于您正在执行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 并扫描返回的列表以找到最大值。

    【讨论】:

      【解决方案3】:

      你确定元素都是非负的吗?

      我会让它像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;
           }               
      
      }
      

      【讨论】:

        【解决方案4】:

        这种递归方法对我有用:

        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);
        }
        

        【讨论】:

          【解决方案5】:

          您可以在队列中使用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
              }
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-03-08
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-10-07
            相关资源
            最近更新 更多