微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

返回一个节点,它在整个树中具有最大的自身及其子节点的总和,但即使当前总和较小,也会更新最大总和

如何解决返回一个节点,它在整个树中具有最大的自身及其子节点的总和,但即使当前总和较小,也会更新最大总和

需要找到子节点和自身之和最大的节点。输入格式:

第 1 行:以空格分隔的级别顺序形式的元素(按照课堂上的做法)。顺序是 -

Root_data,n (No_Of_Child_Of_Root),n 个子元素,等等

输出格式:总和最大的节点。

它返回正确的答案,但如果您通过取消对打印语句的注释来运行代码,您可以看到最大总和已更改,即使当前总和小于最大总和。

public class Solution {

/*  TreeNode structure 
 * 
 * class TreeNode<T> {
    T data;
    ArrayList<TreeNode<T>> children;

    TreeNode(T data){
        this.data = data;
        children = new ArrayList<TreeNode<T>>();
    }
}*/




public static TreeNode<Integer> maxSumNode(TreeNode<Integer> root){
        // Write your code here
        return maxSumNode(root,0);
    }
    
    public static TreeNode<Integer> maxSumNode(TreeNode<Integer> root,int maxSum){
    
    if(root.children.size() == 0){
        return null;
        
    }
    
    TreeNode<Integer> maxNode = null;
    int tempSum = root.data;
    for(int i = 0 ; i < root.children.size() ; ++i){
        tempSum += root.children.get(i).data;
    }
    if(tempSum > maxSum){
        maxSum = tempSum;
        maxNode = root;
        
    }
    //System.out.println("Maxnum Now for "+root.data+" is: "+ maxSum);
    
    for(int i = 0 ; i < root.children.size() ; ++i){
        TreeNode<Integer> temp = maxSumNode(root.children.get(i),maxSum);
        if(temp == null){
            continue;
        }
        if(temp != null){
            maxNode = temp;
        }
    }
    return maxNode;
}
}

例如,如果我给出输入: 5 3 1 2 3 1 15 2 4 5 1 6 0 0 0 0

我得到了正确的输出,但 maxSum 很奇怪:

Result

解决方法

您的问题:

  1. 设置 maxNode 时,不检查其旧值,
  2. 并且您只能向下传递 maxNode,而不是向上/平行传递。将 int 作为参数传递是按值传递的,因此您不是指全局值,而是每个方法调用都有自己的值。解决方案 1 直接解决了这个问题。

可能的解决方案:

  1. 作为参数,您可以传递一些包含数字的类。引用本身发生变化(按值传递),但寻址对象始终保持不变。所以你总是在同一个号码上读/写。

  2. 或者你可以有一个成员变量(静态或非静态),但在访问时要非常小心。

  3. 第三,您可以使用统计地图或优先级队列,其中添加了所有结果,当所有结果都完成后,您选择最大值。

参数解法是最简单、最安全、最高效的。如果 maxSumNode 同时运行多次,则静态更容易,但非常不安全。最后一个简单但效率不高。

/更新:

这是解决方案 #1 的示例。还有一个测试。 这有很多额外的代码来显示可以实现的不同样式。

package stackoverflow;

import java.util.ArrayList;


public class MaxSumNode {

    /**
     * This is a partial implementation of the real TreeNode class,for local implementation only.
     * Remove when you have accedd to the real TreeNode class.
     */
    private static class TreeNode<T> {
        T                       data;
        ArrayList<TreeNode<T>>  children;

        public TreeNode(final T pData) {
            this.data = pData;
            children = new ArrayList<>();
        }

        public TreeNode<T> addChild(final TreeNode<T> pChild) {
            if (children == null) children = new ArrayList<>();
            children.add(pChild);
            return pChild; // used for builder syntax
        }
    }

    /**
     * This is our class that contains the maximum and some additional infos (the max Node itself for example).
     * This is private because it will not be used outside this class.
     */
    private static class CounterReference<T> {
        public int  nodeSum = 0;
        public T    node    = null;
        public CounterReference() {}
    }

    public enum Mode {
        ROOT_ONLY,ALL_LEVELS,ONLY_LEVEL_ONE,LEVEL_ONE_AND_BELOW
    }



    /**
     * Public method that returns calculations of a pre-set mode
     */
    public static CounterReference<TreeNode<Integer>> maxSumNode(final TreeNode<Integer> root) {
        return maxSumNode(root,Mode.ALL_LEVELS);
    }



    /**
     * Our only public 'intelligent' function,i.e. apart from the 2 simple helper functions.
     * Here we set up for the calculations,and decide what range we actually want to consider in out calculations.
     */
    public static CounterReference<TreeNode<Integer>> maxSumNode(final TreeNode<Integer> root,final Mode pMode) {
        final CounterReference<TreeNode<Integer>> cr = new CounterReference<>();

        // 4 different cases,depending on what you need. select ONE of those,comment out the rest
        switch (pMode) {
            case ROOT_ONLY: { // case 1: this case ONLY checks the root (level-0) element
                checkNode(root,cr,false);
                break;
            }
            case ALL_LEVELS: { // case 2: this case checks ALL elements,on ANY level
                checkNode(root,true);
                break;
            }
            case ONLY_LEVEL_ONE: { // case 3: this case only checks level-1 elements (no root element,no child-children
                if (root != null && root.children != null && root.children.size() > 0) {
                    for (final TreeNode<Integer> cs : root.children) {
                        checkNode(cs,false);
                    }
                }
                break;
            }
            case LEVEL_ONE_AND_BELOW: { // case 4: this case checks level-1 elements and down wards,effectively leaving out the root element
                if (root != null && root.children != null && root.children.size() > 0) {
                    for (final TreeNode<Integer> cs : root.children) {
                        checkNode(cs,true);
                    }
                }
                break;
            }
            default:
                throw new IllegalArgumentException("Unknown Mode '" + pMode + "'!");
        }

        return cr;
    }

    /**
     * This node checks given Node and updates CounterReference if needed.
     * This is private,because this method is only used by {@link #maxSumNode(TreeNode)} and will not be used outside this class
     */
    private static void checkNode(final TreeNode<Integer> pNode,final CounterReference<TreeNode<Integer>> pCR,final boolean pRecursive) {
        if (pNode == null) return;

        final int sum = getWeightOfNodeAndDirectChildren(pNode);
        // compare local result with global result
        if (sum > pCR.nodeSum) {
            // we found a new max,so update counter
            pCR.nodeSum = sum;
            pCR.node = pNode;
        }

        // maybe do a recursive check of children and sub-children and sub-sub-children etc
        if (pRecursive && pNode.children != null && pNode.children.size() > 0) {
            for (final TreeNode<Integer> childNode : pNode.children) {
                checkNode(childNode,pCR,pRecursive);
            }
        }
    }



    /*
     * Our helper methods,to make the above code easier
     */

    public static int getWeightOfNodeAndDirectChildren(final TreeNode<Integer> pNode) {
        if (pNode == null) return 0;
        if (pNode.data == null) return 0;

        int sum = 0;
        sum += getWeightOfNode(pNode);
        if (pNode.children != null && pNode.children.size() > 0) {
            for (final TreeNode<Integer> childNode : pNode.children) {
                sum += getWeightOfNode(childNode);
            }
        }

        return sum;
    }

    public static int getWeightOfNode(final TreeNode<Integer> root) {
        if (root == null) return 0;
        if (root.data == null) return 0;
        return root.data.intValue();
    }



    /**
     * Our test method
     */

    public static void main(final String[] args) {
        final TreeNode<Integer> root = new TreeNode<>(Integer.valueOf(3));
        root.addChild(new TreeNode<>(Integer.valueOf(5)));

        final TreeNode<Integer> right = root.addChild(new TreeNode<>(Integer.valueOf(7)));
        right.addChild(new TreeNode<>(Integer.valueOf(13)));
        final TreeNode<Integer> rightRight = right.addChild(new TreeNode<>(Integer.valueOf(17)));
        right.addChild(new TreeNode<>(Integer.valueOf(19)));

        rightRight.addChild(new TreeNode<>(Integer.valueOf(23)));
        rightRight.addChild(new TreeNode<>(Integer.valueOf(29)));

        final TreeNode<Integer> left = root.addChild(new TreeNode<>(Integer.valueOf(11)));
        left.addChild(new TreeNode<>(Integer.valueOf(31)));

        final TreeNode<Integer> leftLeft = left.addChild(new TreeNode<>(Integer.valueOf(37)));
        leftLeft.addChild(new TreeNode<>(Integer.valueOf(41)));
        leftLeft.addChild(new TreeNode<>(Integer.valueOf(43)));


        System.out.println("The tree:");
        printNode(root,0);
        System.out.println();

        System.out.println("The calculation modes:");
        for (final Mode mode : Mode.values()) {
            System.out.println("\tMode: " + mode);
            final CounterReference<TreeNode<Integer>> result = maxSumNode(root,mode);
            if (result == null || result.node == null) {
                System.out.println("\n\n0.o NOO!11!! We do NOT havea result!");
            } else {
                System.out.println("\t\tNode " + result.node.data.intValue() + " with max " + result.nodeSum);
            }
        }

        System.out.println("All done,exiting...");
    }



    private static void printNode(final TreeNode<Integer> pRoot,final int pDepth) {
        if (pRoot == null) return;

        for (int i = 0; i < pDepth; i++) {
            System.out.print("\t");
        }
        System.out.println(pRoot.data);

        if (pRoot.children != null && pRoot.children.size() > 0) {
            for (final TreeNode<Integer> c : pRoot.children) {
                printNode(c,pDepth + 1);
            }
        }
    }


}

// 更新: 修复了 checkNode() 中的一个错误,用 if ... return 替换了 if ... {},因为提前返回会阻止检查孩子,即使他们可能在更深的层次上找到新的最大值。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。