Longest consecutive sequence in Binary tree - data-structures

I'm trying to implement the logic for "Longest consecutive sequence in Binary tree". The logic I have implemented inside the method { longestConsecutivePath } is not working as expected for the tree structure. It is giving me the lognest path length as 5.
Output:
curLength : 5
BSTNode node = new BSTNode(1);
node.setRight(new BSTNode(2));
node.getRight().setRight(new BSTNode(3));
node.getRight().getRight().setRight(new BSTNode(4));
node.getRight().getRight().getRight().setRight(new BSTNode(5));
node.getRight().setLeft(new BSTNode(7));
node.getRight().getLeft().setLeft(new BSTNode(8));
node.getRight().getLeft().getLeft().setLeft(new BSTNode(9));
node.getRight().getLeft().getLeft().getLeft().setLeft(new BSTNode(10));
node.getRight().getLeft().getLeft().getLeft().getLeft().setLeft(new BSTNode(11));
node.getRight().getLeft().getLeft().getLeft().getLeft().getLeft().setLeft(new BSTNode(12));
Class implementing the Longest Consecutive sequence logic:
public class LongestConsecutivePath {
static BSTNode root = null;
public LongestConsecutivePath() {
root = createBinaryTree();
System.out.println("Before finding the longest consecutive path:");
inorder();
}
public void inorder() {
if (null == root) {
return;
}
inorder(root);
}
private void inorder(BSTNode node) {
if (null != node) {
inorder(node.getLeft());
System.out.print(node.getData() + " ");
inorder(node.getRight());
}
}
public BSTNode createBinaryTree() {
BSTNode node = new BSTNode(1);
node.setRight(new BSTNode(2));
node.getRight().setRight(new BSTNode(3));
node.getRight().getRight().setRight(new BSTNode(4));
node.getRight().getRight().getRight().setRight(new BSTNode(5));
node.getRight().setLeft(new BSTNode(7));
node.getRight().getLeft().setLeft(new BSTNode(8));
node.getRight().getLeft().getLeft().setLeft(new BSTNode(9));
node.getRight().getLeft().getLeft().getLeft().setLeft(new BSTNode(10));
node.getRight().getLeft().getLeft().getLeft().getLeft().setLeft(new BSTNode(11));
node.getRight().getLeft().getLeft().getLeft().getLeft().getLeft().setLeft(new BSTNode(12));
return node;
}
public int longestConsecutivePath() {
if (null == root) {
return 0;
}
return longestConsecutivePath(root, 0, root.getData() + 1);
}
public int longestConsecutivePath(BSTNode node, int curLength,
int targetLength) {
if (null == node) {
return curLength;
}
if (node.getData() == targetLength) {
System.out.println("\nnode data value: "+node.getData());
curLength += 1;
longestPath = curLength;
} else {
curLength = 1;
}
longestLeft = longestConsecutivePath(node.getLeft(), curLength,
node.getData() + 1);
longestRight = longestConsecutivePath(node.getRight(), curLength,
node.getData() + 1);
return Math.max(curLength, Math.max(longestLeft, longestRight));
}
public static void main(String[] args) {
LongestConsecutivePath consecutivePath = new LongestConsecutivePath();
int curLength = consecutivePath.longestConsecutivePath();
System.out.println("\ncurLength : " + curLength);
}
}
BSTNode.java
public class BSTNode {
BSTNode left, right;
int data;
/* Default constructor */
public BSTNode() {
left = null;
right = null;
data = 0;
}
/* Constructor */
public BSTNode(int data) {
left = null;
right = null;
this.data = data;
}
public BSTNode getLeft() {
return left;
}
public void setLeft(BSTNode left) {
this.left = left;
}
public BSTNode getRight() {
return right;
}
public void setRight(BSTNode right) {
this.right = right;
}
public int getData() {
return data;
}
public void setData(int data) {
this.data = data;
}
}

Related

How to create a Binary Tree using a String array?

I am given an assignment where I need to do the following:
input your binary tree as an array, using the array representation and node labels A, ..., J, as Strings. Label null stands for a non-existent node, not for a node having a value of null.
Check the validity of your binary tree input: each node, excepting the root, should have a father.
Generate the dynamic memory implementation of the tree, using only the nodes with labels different than null.
So far I have:
public class Project1{
public static void main(String[] args){
String[] input = new String[]{"A","B","C","D","E","F","G","H","I","J"};
}
public class BinaryTree<T> implements java.io.Serializable{
private T data;
private BinaryTree<T> left;
private BinaryTree<T> right;
public BinaryTree(T data){
this.data = data;
left = null;
right = null;
}
public T getData(){
return data;
}
public void attachLeft(BinaryTree<T> tree){
if(tree != null){
left = tree;
}
}
public void attachRight(BinaryTree<T> tree){
if(tree != null){
right = tree;
}
}
public BinaryTree<T> detachLeft(){
BinaryTree<T> t = left;
left = null;
return t;
}
public BinaryTree<T> detachRight(){
BinaryTree<T> t = right;
right = null;
return t;
}
public boolean isEmpty(){
return data == null;
}
public void inOrder(BinaryTree<T> tree){
if (tree != null){
inOrder(tree.left);
System.out.println(tree.getData());
inOrder(tree.right);
}
}
public void preOrder(BinaryTree<T> tree){
if(tree != null){
System.out.println(tree.getData());
preOrder(tree.left);
preOrder(tree.right);
}
}
public void postOrder(BinaryTree<T> tree){
if(tree != null){
postOrder(tree.left);
postOrder(tree.right);
System.out.println(tree.getData());
}
}
}
What I don't understand is how to create a BinaryTree using my data from the string array

Spring Error while using filter and wrapper

I'm using the filter to check user rights.
Problem in comparing session value to param value is occurred and resolution load is applied using wrapper.
However, the following error message came out.
List<Map<String,Object>> loginInfo = (List<Map<String,Object>>)session.getAttribute("loginSession");
if loginInfo.get(0).get("user_type").equals("1") || loginInfo.get(0).get("user_type").equals("2"))
{
chain.doFilter(req, res);
}
else
{
RereadableRequestWrapper wrapperRequest = new RereadableRequestWrapper(request);
String requestBody= IOUtils.toString(wrapperRequest.getInputStream(), "UTF-8");
Enumeration<String> reqeustNames = request.getParameterNames();
if(requestBody == null) {
}
Map<String,Object> param_map = new ObjectMapper().readValue(requestBody, HashMap.class);
String userId_param = String.valueOf(param_map.get("customer_id"));
System.out.println(userId_param);
if( userId_param == null || userId_param.isEmpty()) {
logger.debug("error, customer_id error");
}
if (!loginInfo.get(0).get("customer_id").equals(userId_param))
{
logger.debug("error, customer_id error");
}
chain.doFilter(wrapperRequest, res);
}
/////////////////////////
here is my wrapper Code.
private boolean parametersParsed = false;
private final Charset encoding;
private final byte[] rawData;
private final Map<String, ArrayList<String>> parameters = new LinkedHashMap<String, ArrayList<String>>();
ByteChunk tmpName = new ByteChunk();
ByteChunk tmpValue = new ByteChunk();
private class ByteChunk {
private byte[] buff;
private int start = 0;
private int end;
public void setByteChunk(byte[] b, int off, int len) {
buff = b;
start = off;
end = start + len;
}
public byte[] getBytes() {
return buff;
}
public int getStart() {
return start;
}
public int getEnd() {
return end;
}
public void recycle() {
buff = null;
start = 0;
end = 0;
}
}
public RereadableRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
String characterEncoding = request.getCharacterEncoding();
if (StringUtils.isBlank(characterEncoding)) {
characterEncoding = StandardCharsets.UTF_8.name();
}
this.encoding = Charset.forName(characterEncoding);
// Convert InputStream data to byte array and store it to this wrapper instance.
try {
InputStream inputStream = request.getInputStream();
this.rawData = IOUtils.toByteArray(inputStream);
} catch (IOException e) {
throw e;
}
}
#Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(this.rawData);
ServletInputStream servletInputStream = new ServletInputStream() {
public int read() throws IOException {
return byteArrayInputStream.read();
}
#Override
public boolean isFinished() {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean isReady() {
// TODO Auto-generated method stub
return false;
}
#Override
public void setReadListener(ReadListener listener) {
// TODO Auto-generated method stub
}
};
return servletInputStream;
}
#Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(this.getInputStream(), this.encoding));
}
#Override
public ServletRequest getRequest() {
return super.getRequest();
}
#Override
public String getParameter(String name) {
if (!parametersParsed) {
parseParameters();
}
ArrayList<String> values = this.parameters.get(name);
if (values == null || values.size() == 0)
return null;
return values.get(0);
}
public HashMap<String, String[]> getParameters() {
if (!parametersParsed) {
parseParameters();
}
HashMap<String, String[]> map = new HashMap<String, String[]>(this.parameters.size() * 2);
for (String name : this.parameters.keySet()) {
ArrayList<String> values = this.parameters.get(name);
map.put(name, values.toArray(new String[values.size()]));
}
return map;
}
#SuppressWarnings("rawtypes")
#Override
public Map getParameterMap() {
return getParameters();
}
#SuppressWarnings("rawtypes")
#Override
public Enumeration getParameterNames() {
return new Enumeration<String>() {
#SuppressWarnings("unchecked")
private String[] arr = (String[])(getParameterMap().keySet().toArray(new String[0]));
private int index = 0;
#Override
public boolean hasMoreElements() {
return index < arr.length;
}
#Override
public String nextElement() {
return arr[index++];
}
};
}
#Override
public String[] getParameterValues(String name) {
if (!parametersParsed) {
parseParameters();
}
ArrayList<String> values = this.parameters.get(name);
String[] arr = values.toArray(new String[values.size()]);
if (arr == null) {
return null;
}
return arr;
}
private void parseParameters() {
parametersParsed = true;
if (!("application/x-www-form-urlencoded".equalsIgnoreCase(super.getContentType()))) {
return;
}
int pos = 0;
int end = this.rawData.length;
while (pos < end) {
int nameStart = pos;
int nameEnd = -1;
int valueStart = -1;
int valueEnd = -1;
boolean parsingName = true;
boolean decodeName = false;
boolean decodeValue = false;
boolean parameterComplete = false;
do {
switch (this.rawData[pos]) {
case '=':
if (parsingName) {
// Name finished. Value starts from next character
nameEnd = pos;
parsingName = false;
valueStart = ++pos;
} else {
// Equals character in value
pos++;
}
break;
case '&':
if (parsingName) {
// Name finished. No value.
nameEnd = pos;
} else {
// Value finished
valueEnd = pos;
}
parameterComplete = true;
pos++;
break;
case '%':
case '+':
// Decoding required
if (parsingName) {
decodeName = true;
} else {
decodeValue = true;
}
pos++;
break;
default:
pos++;
break;
}
} while (!parameterComplete && pos < end);
if (pos == end) {
if (nameEnd == -1) {
nameEnd = pos;
} else if (valueStart > -1 && valueEnd == -1) {
valueEnd = pos;
}
}
if (nameEnd <= nameStart) {
continue;
// ignore invalid chunk
}
tmpName.setByteChunk(this.rawData, nameStart, nameEnd - nameStart);
if (valueStart >= 0) {
tmpValue.setByteChunk(this.rawData, valueStart, valueEnd - valueStart);
} else {
tmpValue.setByteChunk(this.rawData, 0, 0);
}
try {
String name;
String value;
if (decodeName) {
name = new String(URLCodec.decodeUrl(Arrays.copyOfRange(tmpName.getBytes(), tmpName.getStart(), tmpName.getEnd())), this.encoding);
} else {
name = new String(tmpName.getBytes(), tmpName.getStart(), tmpName.getEnd() - tmpName.getStart(), this.encoding);
}
if (valueStart >= 0) {
if (decodeValue) {
value = new String(URLCodec.decodeUrl(Arrays.copyOfRange(tmpValue.getBytes(), tmpValue.getStart(), tmpValue.getEnd())), this.encoding);
} else {
value = new String(tmpValue.getBytes(), tmpValue.getStart(), tmpValue.getEnd() - tmpValue.getStart(), this.encoding);
}
} else {
value = "";
}
if (StringUtils.isNotBlank(name)) {
ArrayList<String> values = this.parameters.get(name);
if (values == null) {
values = new ArrayList<String>(1);
this.parameters.put(name, values);
}
if (StringUtils.isNotBlank(value)) {
values.add(value);
}
}
} catch (DecoderException e) {
// ignore invalid chunk
}
tmpName.recycle();
tmpValue.recycle();
}
}
and Error Message is com.fasterxml.jackson.databind.JsonMappingException: No content to map due to end-of-input
I Don't know why this problem happened...

Why generating a Tree according to initial depth is infinite loop (recursion)?

Somebody help me to find the cause of infinite loop (recursion) ?
root = generate_tree(0) // only the root (0 initial_depth)
root = generate_tree(1) // root and two children (1 initial_depth)
0 or 1 initial_depth is working properly but if greater than 1 it will
cause an infinite loop.
Here's my Pseudo Code of creating a Tree according to initial depth
class Node
children = []
generate_subtree()
//let assume it will create two random nodes and pass it to children
children = two random nodes
Node generate_tree(initial_depth)
if initial_depth == 0
return a random Node
else
root = random node
grow_tree(root, initial_depth)
return root;
grow_tree(tree, init_depth)
if initial_depth == 1
tree.generate_subtree()
else if initial_depth > 1
tree.generate_subtree()
for subtree in tree.children
grow_tree(subtree, initial_depth - 1)
Update
I included my actual code
Im working on Unity with C# script
public List<GNode> TERMINALS = new List<GNode>
{
new CanMove_UP(),
new CanMove_DOWN(),
new CanMove_LEFT(),
new CanMove_RIGHT()
};
public List<GNode> NODES = new List<GNode>
{
new ConstantNum(),
new RandomNum()
};
Main Program
let's say i want to create a tree
Tree tree1 = new Tree(0, NODES, TERMINALS); //working properly
Tree tree2 = new Tree(1, NODES, TERMINALS); //working properly
Tree tree3 = new Tree(2, NODES, TERMINALS); //it will cause infinite loop
GNode.cs
using System;
using System.Collections.Generic;
namespace GP
{
public abstract class GNode
{
public const float TERMINAL_RATIO = 0.2f;
public String data { get; private set; }
public bool is_terminal { get; private set; }
public int depth { get; private set; }
public GNode[] children { get; private set; }
public abstract void initialize(int depth = 0);
public abstract void generate_subtree(List<GNode> nodes, List<GNode> terminals);
public GNode() { }
public GNode(String data, bool is_terminal, int depth = 0)
{
this.initialize(data, is_terminal, depth);
}
protected void initialize(String data, bool is_terminal, int depth = 0)
{
this.data = data;
this.is_terminal = is_terminal;
this.depth = depth;
this.children = new GNode[0];
}
protected void generate_subtree(List<GNode> nodes, List<GNode> terminals, int num_of_childrens)
{
List<GNode> classes = new List<GNode>();
for (int i = 0; i < num_of_childrens; i++)
{
if (nodes.Count > 0 && Utility.GetRandomFloat() > GNode.TERMINAL_RATIO)
classes.Add(nodes[Utility.GetRandomNumber(0, nodes.Count)]);
else
classes.Add(terminals[Utility.GetRandomNumber(0, terminals.Count)]);
classes[i].initialize(this.depth + 1);
}
this.children = classes.ToArray();
}
}
#region NODES
public class ConstantNum : GNode
{
public ConstantNum(int depth = 0)
{
this.initialize(depth);
}
public override void initialize(int depth = 0)
{
base.initialize(Utility.GetRandomNumber(0, 9).ToString(), true, depth);
}
public override void generate_subtree(List<GNode> nodes, List<GNode> terminals)
{
base.generate_subtree(nodes, terminals, 2);
}
}
public class RandomNum : GNode
{
public RandomNum(int depth = 0)
{
this.initialize(depth);
}
public override void initialize(int depth = 0)
{
base.initialize("random", true, depth);
}
public override void generate_subtree(List<GNode> nodes, List<GNode> terminals)
{
base.generate_subtree(nodes, terminals, 2);
}
}
#endregion
#region TERMINALS
public class MeasureNode : GNode
{
public String Measure { set; private get; }
public override void initialize(int depth = 0)
{
base.initialize(this.Measure, true, depth);
}
public override void generate_subtree(List<GNode> nodes, List<GNode> terminals)
{
base.generate_subtree(nodes, terminals, 2);
}
}
public class CanMove_UP : MeasureNode
{
public override void initialize(int depth = 0)
{
base.Measure = "CanMove_UP";
base.initialize(depth);
}
}
public class CanMove_DOWN : MeasureNode
{
public override void initialize(int depth = 0)
{
base.Measure = "CanMove_DOWN";
base.initialize(depth);
}
}
public class CanMove_LEFT : MeasureNode
{
public override void initialize(int depth = 0)
{
base.Measure = "CanMove_LEFT";
base.initialize(depth);
}
}
public class CanMove_RIGHT : MeasureNode
{
public override void initialize(int depth = 0)
{
base.Measure = "CanMove_RIGHT";
base.initialize(depth);
}
}
#endregion
}
Tree.cs
using System;
using System.Collections.Generic;
namespace GP
{
public class Tree
{
private int initial_depth;
private List<GNode> nodes;
private List<GNode> terminals;
private GNode root;
public Tree(int initial_depth, List<GNode> nodes, List<GNode> terminals, GNode root = null)
{
this.initial_depth = initial_depth;
this.nodes = nodes;
this.terminals = terminals;
this.root = root;
if (root == null)
this.root = this.generate_tree(initial_depth, nodes, terminals);
}
public GNode generate_tree(int initial_depth, List<GNode> nodes, List<GNode> terminals)
{
if (initial_depth == 0)
return terminals[Utility.GetRandomNumber(0, terminals.Count)]; //construct a random node from terminals
else
{
GNode tree;
if (Utility.GetRandomFloat() <= GNode.TERMINAL_RATIO)
tree = terminals[Utility.GetRandomNumber(0, terminals.Count)];
else
tree = nodes[Utility.GetRandomNumber(0, nodes.Count)];
this.grow_tree(tree, initial_depth, nodes, terminals);
return tree;
}
}
public void grow_tree(GNode tree, int init_depth, List<GNode> nodes, List<GNode> terminals)
{
if (initial_depth == 1)
tree.generate_subtree(new List<GNode>(), terminals); //empty nodes
else if (initial_depth > 1)
{
tree.generate_subtree(nodes, terminals);
foreach (GNode subtree in tree.children)
this.grow_tree(subtree, initial_depth - 1, nodes, terminals);
}
}
}
}
Utility.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public static class Utility
{
private static readonly System.Random getRandom = new System.Random();
public static int GetRandomNumber(int min, int max)
{
lock (getRandom)
{
return getRandom.Next(min, max);
}
}
public static int GetRandomNumber(int max)
{
return GetRandomNumber(0, max);
}
public static float GetRandomFloat(float min = 0.0f, float max = 1.0f)
{
return Random.Range(min, max);
}
}
class Node:
def __init__(self):
self.children = []
def generate_subtree(self):
self.children.append(Node())
self.children.append(Node())
def generate_tree(initial_depth):
if initial_depth == 0:
return Node()
else:
root = Node()
grow_tree(root, initial_depth)
return root
def grow_tree(tree, initial_depth):
if initial_depth == 1:
tree.generate_subtree()
elif initial_depth > 1:
tree.generate_subtree()
for subtree in tree.children:
grow_tree(subtree, initial_depth - 1)
tree = generate_tree(4)
I have translated the exact pseudo-code that you have written and it is working fine.
Can you post your code, or you can just verify from mine what you are missing.

Queue data structure requiring K accesses before removal

I need a specialized queue-like data structure. It can be used by multiple consumers, but each item in queue must be removed from queue after k consumers read it.
Is there any production ready implementation? Or Should I implement a queue with read-counter in each item, and handle item removal myself?
Thanks in advance.
I think this is what you are looking for. Derived from the source code for BlockingQueue. Caveat emptor, not tested.
I tried to find a way to wrap Queue, but Queue doesn't expose its concurrency members, so you can't get the right semantics.
public class CountingQueue<E> {
private class Entry {
Entry(int count, E element) {
this.count = count;
this.element = element;
}
int count;
E element;
}
public CountingQueue(int capacity) {
if (capacity <= 0) {
throw new IllegalArgumentException();
}
this.items = new Object[capacity];
this.lock = new ReentrantLock(false);
this.condition = this.lock.newCondition();
}
private final ReentrantLock lock;
private final Condition condition;
private final Object[] items;
private int takeIndex;
private int putIndex;
private int count;
final int inc(int i) {
return (++i == items.length) ? 0 : i;
}
final int dec(int i) {
return ((i == 0) ? items.length : i) - 1;
}
private static void checkNotNull(Object v) {
if (v == null)
throw new NullPointerException();
}
/**
* Inserts element at current put position, advances, and signals.
* Call only when holding lock.
*/
private void insert(int count, E x) {
items[putIndex] = new Entry(count, x);
putIndex = inc(putIndex);
if (count++ == 0) {
// empty to non-empty
condition.signal();
}
}
private E extract() {
Entry entry = (Entry)items[takeIndex];
if (--entry.count <= 0) {
items[takeIndex] = null;
takeIndex = inc(takeIndex);
if (count-- == items.length) {
// full to not-full
condition.signal();
}
}
return entry.element;
}
private boolean waitNotEmpty(long timeout, TimeUnit unit) throws InterruptedException {
long nanos = unit.toNanos(timeout);
while (count == 0) {
if (nanos <= 0) {
return false;
}
nanos = this.condition.awaitNanos(nanos);
}
return true;
}
private boolean waitNotFull(long timeout, TimeUnit unit) throws InterruptedException {
long nanos = unit.toNanos(timeout);
while (count == items.length) {
if (nanos <= 0)
return false;
nanos = condition.awaitNanos(nanos);
}
return true;
}
public boolean put(int count, E e) {
checkNotNull(e);
final ReentrantLock localLock = this.lock;
localLock.lock();
try {
if (count == items.length)
return false;
else {
insert(count, e);
return true;
}
} finally {
localLock.unlock();
}
}
public boolean put(int count, E e, long timeout, TimeUnit unit)
throws InterruptedException {
checkNotNull(e);
final ReentrantLock localLock = this.lock;
localLock.lockInterruptibly();
try {
if (!waitNotFull(timeout, unit)) {
return false;
}
insert(count, e);
return true;
} finally {
localLock.unlock();
}
}
public E get() {
final ReentrantLock localLock = this.lock;
localLock.lock();
try {
return (count == 0) ? null : extract();
} finally {
localLock.unlock();
}
}
public E get(long timeout, TimeUnit unit) throws InterruptedException {
final ReentrantLock localLock = this.lock;
localLock.lockInterruptibly();
try {
if (waitNotEmpty(timeout, unit)) {
return extract();
} else {
return null;
}
} finally {
localLock.unlock();
}
}
public int size() {
final ReentrantLock localLock = this.lock;
localLock.lock();
try {
return count;
} finally {
localLock.unlock();
}
}
public boolean isEmpty() {
final ReentrantLock localLock = this.lock;
localLock.lock();
try {
return count == 0;
} finally {
localLock.unlock();
}
}
public int remainingCapacity() {
final ReentrantLock lock= this.lock;
lock.lock();
try {
return items.length - count;
} finally {
lock.unlock();
}
}
public boolean isFull() {
final ReentrantLock localLock = this.lock;
localLock.lock();
try {
return items.length - count == 0;
} finally {
localLock.unlock();
}
}
public void clear() {
final ReentrantLock localLock = this.lock;
localLock.lock();
try {
for (int i = takeIndex, k = count; k > 0; i = inc(i), k--)
items[i] = null;
count = 0;
putIndex = 0;
takeIndex = 0;
condition.signalAll();
} finally {
localLock.unlock();
}
}
}
A memory efficient way that retains the info you need:
Each queue entry becomes a
Set<ConsumerID>
so that you ensure the k times are for k distinct consumers: your app logic checks if the
set.size()==k
and removes it from queue in that case.
In terms of storage: you will have tradeoffs of which Set implementation based on
size and type of the ConsumerID
speed of retrieval requirement
E.g if k is very small and your queue retrieval logic has access to a
Map<ID,ConsumerId>
then you could have simply an Int or even a Short or Byte depending on # distinct ConsumerID's and possibly store in an Array . This is slower than accessing a set since it would be traversed linearly - but for small K that may be reasonable.

get average value from a tree of nodes

I have to implement this method:
public int GetAverage(Node root){
//TODO implement
}
this method should get average value of all nodes of root tree. where :
public interface Node {
int getValue();
List<Node> getNodes();
}
do you have any ideas how to implement this method?
thank you
my attempt:
public static double value;
public static int count;
public static double getAverage(Node root) {
count++;
value += root.getValue();
for (Node node : root.getNodes()) {
getAverage(node);
}
return value / count;
}
but how to do it without the static fields outside of the method?
Simply traverse through all nodes and remember the count and the overall sum of all values. Then calculate the average. This is an example written in Java.
public interface INode {
int getValue();
List<INode> getNodes();
}
public class Node implements INode {
private List<INode> children = new ArrayList<INode>();
private int value;
#Override
public int getValue() {
return value;
}
#Override
public List<INode> getNodes() {
return children;
}
public static int getAverage(INode root) {
if (root == null)
return 0;
Counter c = new Counter();
calculateAverage(root, c);
return c.sum / c.count;
}
class Counter {
public int sum;
public int count;
}
private static void calculateAverage(INode root, Counter counter) {
if (root == null)
return;
counter.sum += root.getValue();
counter.count++;
// recursively through all children
for (INode child : root.getNodes())
calculateAverage(child, counter);
}
}
public static double getAverage(Node root) {
Pair p = new Pair(0,0);
algo(root, p);
return ((double) p.element1) / ((double) p.element2);
}
private static void algo(Node root, Pair acc) {
for(Node child : root.getNodes()) {
algo(child, acc);
}
acc.sum += root.getValue();
acc.nbNodes++;
}
With Pair defined as follows:
public class Pair {
public int sum;
public int nbNodes;
public Pair(int elt1, int elt2) {
this.sum = elt1;
this.nbNodes = elt2;
}
}

Resources