简体   繁体   中英

Return a Node having maximum sum of itself and its children in the entire tree but the max sum is being updated even if the current sum is less

Need to find the node with the maximum sum of children and itself. The Input format:

Line 1: Elements in level order form separated by space (as per done in class). Order is -

Root_data, n (No_Of_Child_Of_Root), n children, and so on for every element

Output format: Node with maximum sum.

It returns correct answers but if you run the code by uncommenting the print statement you can see that the max sum is altered even though the current sum is less than the max sum.

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

for example if i give the input: 5 3 1 2 3 1 15 2 4 5 1 6 0 0 0 0

I get the output correctly but the maxSum is weird:

结果

Your problems:

  1. When setting maxNode, you don't check its old value,
  2. AND you only pass maxNode downwards, not upwards/parallel. Passing int as parameter is pass-by-value, so you're not referring to a global value, but each method call gets its own value. Solution 1 directly addresses that.

Possible Solutions:

  1. As parameter you could pass some class that contains the number. The reference itself changes (pass-by-value), but the addressed object always stays the same. So you always read/write on the same number.

  2. Or you could have a member variable (static or non-static) but be really careful about access.

  3. And third, you could use a statistics map or priority queue where ALL results are added, and when all is done, you choose the max.

The parameter solution is the easiest, safest and most efficient. The static is even easier, but disastrously unsafe, if maxSumNode gets run multiple times simultaneuosly. Last one is easy but not efficient.

/UPDATE:

Here's an example for solution #1. And a test. This has lots of additional code to show the different styles that can be implemented.

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


}

// UPDATE: Fixed a mistake inside checkNode() replaced if... return with if... {} because early return would prevent check of children, even though they might, on some deeper levels, find a new max.

Please check the below code for a simple solution.

public static int maxSum;
public static TreeNode<Integer> resNode;
public static TreeNode<Integer> maxSumNode(TreeNode<Integer> root){
    maxSum=0;
    helper(root);
    return resNode;
}
public static void helper(TreeNode<Integer> root){
    if(root==null){
        return;
    }
    int currSum = root.data;
    int count = root.children.size();
    for (int i = 0; i < count; i++){
        currSum += root.children.get(i).data;
        helper(root.children.get(i));
    }
    if (currSum > maxSum){
        resNode = root;
        maxSum = currSum;
    }
    return;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM