问题描述
需要找到子节点和自身之和最大的节点。输入格式:
第 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 很奇怪:
解决方法
您的问题:
- 设置 maxNode 时,不检查其旧值,
- 并且您只能向下传递 maxNode,而不是向上/平行传递。将 int 作为参数传递是按值传递的,因此您不是指全局值,而是每个方法调用都有自己的值。解决方案 1 直接解决了这个问题。
可能的解决方案:
-
作为参数,您可以传递一些包含数字的类。引用本身发生变化(按值传递),但寻址对象始终保持不变。所以你总是在同一个号码上读/写。
-
或者你可以有一个成员变量(静态或非静态),但在访问时要非常小心。
-
第三,您可以使用统计地图或优先级队列,其中添加了所有结果,当所有结果都完成后,您选择最大值。
参数解法是最简单、最安全、最高效的。如果 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 ... {}
,因为提前返回会阻止检查孩子,即使他们可能在更深的层次上找到新的最大值。