I'm trying to solve UVa 10461 Difference problem using Java and I am pretty sure of the logic of my code because I actually submitted this logic in C++ and got accepted but when I was trying to submit it using Java, I got Runtime error.
The problem asks to calculate the maximum possible difference among all possible completion times of a particular job.
Any ideas
import java.io.*;
import java.util.*;
class Main {
public static void main(String[] args) throws IOException {
BufferedReader bufferReader = new BufferedReader(new InputStreamReader(System.in));
PrintWriter out = new PrintWriter(System.out);
StringTokenizer st = new StringTokenizer(bufferReader.readLine());
int v = Integer.parseInt(st.nextToken());
int e = Integer.parseInt(st.nextToken());
int count = 1;
while (v != 0 || e != 0) {
int[] jobs = new int[v];
List<List<Integer>> parents = new ArrayList<>(v);
List<List<Integer>> children = new ArrayList<>(v);
int sum = 0;
st = new StringTokenizer(bufferReader.readLine());
for (int i = 0; i < v; i++) {
jobs[i] = Integer.parseInt(st.nextToken());
parents.add(new ArrayList<>());
children.add(new ArrayList<>());
sum += jobs[i];
}
for (int i = 0; i < e; i++) {
st = new StringTokenizer(bufferReader.readLine());
int from = Integer.parseInt(st.nextToken()) - 1;
int to = Integer.parseInt(st.nextToken()) - 1;
children.get(from).add(to);
parents.get(to).add(from);
}
st = new StringTokenizer(bufferReader.readLine());
int q = Integer.parseInt(st.nextToken());
st = new StringTokenizer(bufferReader.readLine());
out.println("Case #" + count++ + ":");
while (q-- > 0) {
int cur = Integer.parseInt(st.nextToken()) - 1;
int max = sum - getJobTime(cur, parents, jobs) - jobs[cur];
int min = getJobTime(cur, children, jobs);
out.println(max - min);
}
out.println();
out.flush();
bufferReader.readLine();
st = new StringTokenizer(bufferReader.readLine());
v = Integer.parseInt(st.nextToken());
e = Integer.parseInt(st.nextToken());
}
bufferReader.close();
out.close();
}
public static int getJobTime(int job, List<List<Integer>> dependencies, int[] jobs) {
Queue<Integer> q = new LinkedList<>();
Set<Integer> set = new HashSet<>();
List<Integer> curDependencies = dependencies.get(job);
for (Integer item : curDependencies) {
q.offer(item);
set.add(item);
}
int count = 0;
while (!q.isEmpty()) {
int cur = q.poll();
count += jobs[cur];
curDependencies = dependencies.get(cur);
for (Integer item : curDependencies) {
if (!set.contains(item)) {
q.offer(item);
set.add(item);
}
}
}
return count;
}
}
Related
Here is my class below, that compares elements in two string arrays, and returns the word with the highest frequency in both arrays. However as visible from the output, the first index is appending none to null in spite of initializing both arrays with the String none. Can someone kindly let me know what I am doing wrong that is leading to this?
public class HelloWorld{
public String[] pro;
public String[] con;
String proSplitter;
String conSplitter;
public HelloWorld() {
this.pro = new String[9];
this.con = new String[9];
for(int i=0;i<this.pro.length;i++)
{
this.pro[i]="none";
this.con[i]="none";
}
}
public String[] getPro() {
return pro;
}
public String[] getCon() {
return con;
}
public void setPro(String pros, int proIndex) {
pro[proIndex] = pros;
}
public void setCon(String cons, int conIndex) {
con[conIndex] = cons;
}
public String[] proWord(){
for(int i=0;i<9;i++)
{
proSplitter = proSplitter + pro[i] + ",";
}
for(int i=0;i<9;i++)
{
conSplitter = conSplitter + con[i] + ",";
}
String[] values = proSplitter.split(",");
for(int i=0;i<values.length;i++)
{
values[i] = values[i].trim();
}
String[] values1 = conSplitter.split(",");
for(int i=0;i<values1.length;i++)
{
values1[i] = values1[i].trim();
}
int [] fr = new int [values.length];
int visited = -1;
for(int i = 0; i < values.length; i++){
int count = 1;
for(int j = i+1; j < values.length; j++){
if(!values[i].equalsIgnoreCase("none"))
{
if(values[i].compareTo(values[j])==0){
count++;
//To avoid counting same element again
fr[j] = visited;
}
}
}
if(fr[i] != visited)
fr[i] = count;
}
int max = fr[0];
int index = 0;
for (int i = 0; i < fr.length; i++)
{
if (max < fr[i])
{
max = fr[i];
index = i;
}
}
int [] fr1 = new int [values1.length];
int visited1 = -1;
for(int i = 0; i < values1.length; i++){
int count1 = 1;
for(int j = i+1; j < values1.length; j++){
if(!values1[i].equalsIgnoreCase("none"))
{
if(values1[i].compareTo(values1[j])==0){
count1++;
//To avoid counting same element again
fr1[j] = visited1;
}
}
}
if(fr1[i] != visited1)
fr1[i] = count1;
}
for(int i = 0;i<values.length;i++)
{
System.out.println("pro = "+values[i]);
}
for(int i = 0;i<values1.length;i++)
{
System.out.println("con = "+values1[i]);
}
int max1 = fr1[0];
int index1 = 0;
for (int i = 0; i < fr1.length; i++)
{
if (max1 < fr1[i])
{
max1 = fr1[i];
index1 = i;
}
}
String sentence[] = new String[2];
if(values[index].equalsIgnoreCase(values1[index1])) {
sentence[0] = "balanced";
}else {
sentence[0] = values[index];
sentence[1] = values1[index1];
}
return sentence;
}
public static void main(String[] args){
HelloWorld tracker = new HelloWorld();
tracker.setPro("Apple, Pear", 1);
tracker.setCon("Banana", 1);
tracker.setPro("Apple", 2);
tracker.setCon("Water Melon", 2);
tracker.setPro("Guava", 3);
tracker.setCon("Ball", 3);
tracker.setPro("Apple", 4);
tracker.setCon("Mango, Plum", 4);
String[] arr = tracker.proWord();
System.out.println("pro = "+arr[0]);
System.out.println("con = "+arr[1]);
}
}
The output being generated is :
pro = nullnone
pro = Apple
pro = Pear
pro = Apple
pro = Guava
pro = Apple
pro = none
pro = none
pro = none
pro = none
con = nullnone
con = Banana
con = Water Melon
con = Ball
con = Mango
con = Plum
con = none
con = none
con = none
con = none
pro = Apple
con = nullnone
As mentioned by Arnaud, the immediate problem is that you're leaving proSplitter uninitialized, so its value is null. Then, when you come to append a string to it with proSplitter = proSplitter + pro[i] + ",";, proSplitter will be converted (effectively) to "null", and then stuff is appended to the end. So, instead, make it "" initially.
However, you've got another problem here, which is that you're mutating a member variable each time you invoke that method - so it's not null (or empty) second time around, it still contains what was there previously.
The fix for that is straightforward: instead of using a member variable, declare these as local variables.
You've also got the problem that you're effectively duplicating the code to count the most frequent thing in an array: this is what methods are for, to allow you to run the same code over different inputs.
You can also make use of library methods. For example:
String mostFrequent(String[] array) {
int maxFreq = 0;
String maxFreqS = "";
for (String s : array) {
if (s.equalsIgnoreCase("none")) continue;
int freq = Collections.frequency(Arrays.asList(array), s);
if (freq > maxFreq) {
maxFreq = freq;
maxFreqS = s;
}
}
return maxFreqS;
}
(There are lots of inefficiencies here. The point is more about writing this as a method, to remove the duplication).
Then you can use this inside your existing method, and it will be a whole lot easier for others - and you - to read.
There is a voice recorder which stores student voice as per roll number on which it was heard earlier. When the attendance process is complete, it will provide a list which would consist of the number of distinct voices. The teacher presents the list to you and asks for the roll numbers of students who were not present in class.
I'm trying to find out roll number of absent students in increasing order.
I wrote this case but some test cases are failing. I'm not sure what values would be in list which is provided by teacher.
There are only two inputs:
no of student
result from voice recorder
So can anyone tell what is missing here
public static void main(String args[]) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
List<Integer> ll = new ArrayList<>();
List<Integer> input = new ArrayList<>();
for (int i = 1; i <= n; i++) {
ll.add(i);
}
String lines = br.readLine();
String[] strs = lines.trim().split("\\s+");
for (int i = 0; i < strs.length; i++) {
input.add(Integer.parseInt(strs[i]));
}
for (int i = 0; i < ll.size(); i++) {
if (input.contains(ll.get(i))) {
continue;
}
else {
System.out.print(ll.get(i));
}
if (i != ll.size() - 1) {
System.out.print(" ");
}
}
}
This works fine and every test case passed.
public static void main(String[] args) throws NumberFormatException, IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int stdCount = Integer.parseInt(br.readLine());
String rollNumbers = br.readLine();
TreeSet<Integer> presentStudents = new TreeSet<Integer>();
String[] rollNoArr = rollNumbers.split(" ");
for(String s : rollNoArr) {
presentStudents.add(Integer.valueOf(s.trim()));
}
for(int i = 1; i <= stdCount; i++) {
if(!presentStudents.contains(i)) {
System.out.print(i);
if(i < stdCount) System.out.print(" ");
}
}
}
Assuming that I'm reading the question correctly, you first input the total number of students in the class. Each student has an assigned number, and you next provide a list of numbers (cooresponding to students present in class) seperated by spaces. Your code was missing a few brackets, which messed things up.
In addition, for this specific case, your logic of:
if (true) {
continue;
}
else{
// Do something
}
Can be made a lot simpler by doing:
if(!true){
// Do something
}
Here is the final code that I touched up:
public static void main(String args[]) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
List<Integer> ll = new ArrayList<>();
List<Integer> input = new ArrayList<>();
for (int i = 1; i <= n; i++) {
ll.add(i);
}
String lines = br.readLine();
String[] strs = lines.trim().split("\\s+");
for (int i = 0; i < strs.length; i++) {
input.add(Integer.parseInt(strs[i]));
}
for (int i = 0; i < ll.size(); i++) {
if (!input.contains(ll.get(i))) {
System.out.print(ll.get(i));
if (i != ll.size() - 1) {
System.out.print(" ");
}
}
}
}
An input of:
6
1 3 4
Results in an output of:
2 5 6
////working code using Java8
{
public static void main(String[] args) throws IOException {
List<Integer> totalRolls;
String[] inputRollsWithProxyStudentsRoll;
try (BufferedReader br = new BufferedReader(new InputStreamReader(System.in))) {
totalRolls = IntStream
.rangeClosed(1, Integer.parseInt(br.readLine()))
.boxed()
.collect(Collectors.toList());
inputRollsWithProxyStudentsRoll = br.readLine().trim().split("\\s+");
}
List<Integer> rollsWithProxyStudentsRoll = Arrays
.stream(inputRollsWithProxyStudentsRoll).map(Integer::parseInt)
.collect(Collectors.toList());
IntStream
.range(0, totalRolls.size())
.filter(i -> !rollsWithProxyStudentsRoll.contains(totalRolls.get(i)))
.forEach(i -> {
System.out.print(totalRolls.get(i));
if (i != totalRolls.size() - 1) System.out.print(" ");
});
}
}
import java.io.*
import java.util.*;
class Test {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] array = new int[n];
for (int i = 0; i < n; i++)
array[i] = sc.nextInt();
for (int i = 1; i <= n; i++) {
for (int j = 0; j < n; j++) {
if (i == array[j]) {
break;
}
if (j == n - 1 && i != array[j]) {
System.out.println(i + " ");
}
}
}
}
}
How to generate an n-gram of a string like:
String Input="This is my car."
I want to generate n-gram with this input:
Input Ngram size = 3
Output should be:
This
is
my
car
This is
is my
my car
This is my
is my car
Give some idea in Java, how to implement that or if any library is available for it.
I am trying to use this NGramTokenizer but its giving n-gram's of character sequence and I want n-grams of word sequence.
I believe this would do what you want:
import java.util.*;
public class Test {
public static List<String> ngrams(int n, String str) {
List<String> ngrams = new ArrayList<String>();
String[] words = str.split(" ");
for (int i = 0; i < words.length - n + 1; i++)
ngrams.add(concat(words, i, i+n));
return ngrams;
}
public static String concat(String[] words, int start, int end) {
StringBuilder sb = new StringBuilder();
for (int i = start; i < end; i++)
sb.append((i > start ? " " : "") + words[i]);
return sb.toString();
}
public static void main(String[] args) {
for (int n = 1; n <= 3; n++) {
for (String ngram : ngrams(n, "This is my car."))
System.out.println(ngram);
System.out.println();
}
}
}
Output:
This
is
my
car.
This is
is my
my car.
This is my
is my car.
An "on-demand" solution implemented as an Iterator:
class NgramIterator implements Iterator<String> {
String[] words;
int pos = 0, n;
public NgramIterator(int n, String str) {
this.n = n;
words = str.split(" ");
}
public boolean hasNext() {
return pos < words.length - n + 1;
}
public String next() {
StringBuilder sb = new StringBuilder();
for (int i = pos; i < pos + n; i++)
sb.append((i > pos ? " " : "") + words[i]);
pos++;
return sb.toString();
}
public void remove() {
throw new UnsupportedOperationException();
}
}
You are looking for ShingleFilter.
Update: The link points to version 3.0.2. This class may be in different package in newer version of Lucene.
This code returns an array of all Strings of the given length:
public static String[] ngrams(String s, int len) {
String[] parts = s.split(" ");
String[] result = new String[parts.length - len + 1];
for(int i = 0; i < parts.length - len + 1; i++) {
StringBuilder sb = new StringBuilder();
for(int k = 0; k < len; k++) {
if(k > 0) sb.append(' ');
sb.append(parts[i+k]);
}
result[i] = sb.toString();
}
return result;
}
E.g.
System.out.println(Arrays.toString(ngrams("This is my car", 2)));
//--> [This is, is my, my car]
System.out.println(Arrays.toString(ngrams("This is my car", 3)));
//--> [This is my, is my car]
/**
*
* #param sentence should has at least one string
* #param maxGramSize should be 1 at least
* #return set of continuous word n-grams up to maxGramSize from the sentence
*/
public static List<String> generateNgramsUpto(String str, int maxGramSize) {
List<String> sentence = Arrays.asList(str.split("[\\W+]"));
List<String> ngrams = new ArrayList<String>();
int ngramSize = 0;
StringBuilder sb = null;
//sentence becomes ngrams
for (ListIterator<String> it = sentence.listIterator(); it.hasNext();) {
String word = (String) it.next();
//1- add the word itself
sb = new StringBuilder(word);
ngrams.add(word);
ngramSize=1;
it.previous();
//2- insert prevs of the word and add those too
while(it.hasPrevious() && ngramSize<maxGramSize){
sb.insert(0,' ');
sb.insert(0,it.previous());
ngrams.add(sb.toString());
ngramSize++;
}
//go back to initial position
while(ngramSize>0){
ngramSize--;
it.next();
}
}
return ngrams;
}
Call:
long startTime = System.currentTimeMillis();
ngrams = ToolSet.generateNgramsUpto("This is my car.", 3);
long stopTime = System.currentTimeMillis();
System.out.println("My time = "+(stopTime-startTime)+" ms with ngramsize = "+ngrams.size());
System.out.println(ngrams.toString());
Output:
My time = 1 ms with ngramsize = 9 [This, is, This is, my, is my, This
is my, car, my car, is my car]
public static void CreateNgram(ArrayList<String> list, int cutoff) {
try
{
NGramModel ngramModel = new NGramModel();
POSModel model = new POSModelLoader().load(new File("en-pos-maxent.bin"));
PerformanceMonitor perfMon = new PerformanceMonitor(System.err, "sent");
POSTaggerME tagger = new POSTaggerME(model);
perfMon.start();
for(int i = 0; i<list.size(); i++)
{
String inputString = list.get(i);
ObjectStream<String> lineStream = new PlainTextByLineStream(new StringReader(inputString));
String line;
while ((line = lineStream.read()) != null)
{
String whitespaceTokenizerLine[] = WhitespaceTokenizer.INSTANCE.tokenize(line);
String[] tags = tagger.tag(whitespaceTokenizerLine);
POSSample sample = new POSSample(whitespaceTokenizerLine, tags);
perfMon.incrementCounter();
String words[] = sample.getSentence();
if(words.length > 0)
{
for(int k = 2; k< 4; k++)
{
ngramModel.add(new StringList(words), k, k);
}
}
}
}
ngramModel.cutoff(cutoff, Integer.MAX_VALUE);
Iterator<StringList> it = ngramModel.iterator();
while(it.hasNext())
{
StringList strList = it.next();
System.out.println(strList.toString());
}
perfMon.stopAndPrintFinalResult();
}catch(Exception e)
{
System.out.println(e.toString());
}
}
Here is my codes to create n-gram. In this case, n = 2, 3. n-gram of words sequence which smaller than cutoff value will ignore from result set. Input is list of sentences, then it parse using a tool of OpenNLP
public static void main(String[] args) {
String[] words = "This is my car.".split(" ");
for (int n = 0; n < 3; n++) {
List<String> list = ngrams(n, words);
for (String ngram : list) {
System.out.println(ngram);
}
System.out.println();
}
}
public static List<String> ngrams(int stepSize, String[] words) {
List<String> ngrams = new ArrayList<String>();
for (int i = 0; i < words.length-stepSize; i++) {
String initialWord = "";
int internalCount = i;
int internalStepSize = i + stepSize;
while (internalCount <= internalStepSize
&& internalCount < words.length) {
initialWord = initialWord+" " + words[internalCount];
++internalCount;
}
ngrams.add(initialWord);
}
return ngrams;
}
Check this out:
public static void main(String[] args) {
NGram nGram = new NGram();
String[] tokens = "this is my car".split(" ");
int i = tokens.length;
List<String> ngrams = new ArrayList<>();
while (i >= 1){
ngrams.addAll(nGram.getNGram(tokens, i, new ArrayList<>()));
i--;
}
System.out.println(ngrams);
}
private List<String> getNGram(String[] tokens, int n, List<String> ngrams) {
StringBuilder strbldr = new StringBuilder();
if (tokens.length < n) {
return ngrams;
}else {
for (int i=0; i<n; i++){
strbldr.append(tokens[i]).append(" ");
}
ngrams.add(strbldr.toString().trim());
String[] newTokens = Arrays.copyOfRange(tokens, 1, tokens.length);
return getNGram(newTokens, n, ngrams);
}
}
Simple recursive function, better running time.
I have managed to create a working solution for "Mixing Milk" for USACO, but the judge says my program takes too long.
I think this has to do with the way I sort the list of Farmers by asking price in lines 29 - 44. Is there any way I can improve the run time?
/*
ID:
LANG: JAVA
TASK: milk
*/
import java.util.*;
import java.io.*;
public class milk {
public static void main(String[] args) throws IOException {
double startTime = System.currentTimeMillis();
BufferedReader s = new BufferedReader(new InputStreamReader(new FileInputStream(new File("test.in"))));
PrintWriter w = new PrintWriter(new File("test.out"));
// BufferedReader s = new BufferedReader(new InputStreamReader(new FileInputStream(new File("milk.in"))));
// PrintWriter w = new PrintWriter(new File("milk.out"));
String[] st = s.readLine().split(" ");
int N = Integer.parseInt(st[0]);
int M = Integer.parseInt(st[1]);
int[] P = new int[M];
int[] A = new int[M];
String[] sets = new String[M];
for (int i = 0; i < M; i++) {
sets[i] = s.readLine();
st = sets[i].split(" ");
P[i] = Integer.parseInt(st[0]);
}
int maxp = ("" + maxVal(P)).length();
for (int i = 0; i < M; i++) {
st = sets[i].split(" ");
while (st[0].length() < maxp) {
st[0] = "0" + st[0];
}
sets[i] = st[0] + " " + st[1];
}
Arrays.sort(sets);
int cap = 0;
for (int i = 0; i < M && cap <= N; i++) {
st = sets[i].split(" ");
P[i] = Integer.parseInt(st[0]);
A[i] = Integer.parseInt(st[1]);
cap += A[i];
}
int sum = 0;
int units = 0;
int a;
for (int i = 0; units < N; i++) {
if (A[i] <= N - units) {
sum = sum + P[i] * A[i];
units += A[i];
} else {
a = N - units;
if (a > A[i]) {
a = A[i];
}
sum = sum + P[i] * a;
units += a;
}
}
System.out.println(units);
System.out.println(sum);
w.println(sum);
w.close();
double endTime = System.currentTimeMillis();
System.out.println("Took " + ((endTime - startTime) / 1000) + " seconds.");
}
public static int maxVal(int[] x) {
int max = 0;
for (int i : x) {
if (i > max) {
max = i;
}
}
return max;
}
}
EDIT: Thanks Andreas!
Changed code and made the time limit:
/*
ID:
LANG: JAVA
TASK: milk
*/
import java.util.*;
import java.io.*;
public class milk {
public static void main(String[] args) throws IOException {
double startTime = System.currentTimeMillis();
// BufferedReader s = new BufferedReader(new InputStreamReader(new FileInputStream(new File("test.in"))));
// PrintWriter w = new PrintWriter(new File("test.out"));
BufferedReader s = new BufferedReader(new InputStreamReader(new FileInputStream(new File("milk.in"))));
PrintWriter w = new PrintWriter(new File("milk.out"));
String temp = s.readLine();
int spc = temp.indexOf(" ");
int N = Integer.parseInt(temp.substring(0, spc));
int M = Integer.parseInt(temp.substring(spc + 1));
System.out.println(N + " " + M);
int[] P = new int[M];
int[] A = new int[M];
Farmer[] f = new Farmer[M];
for (int i = 0; i < M; i++) {
temp = s.readLine();
spc = temp.indexOf(" ");
f[i] = new Farmer(Integer.parseInt(temp.substring(0, spc)), Integer.parseInt(temp.substring(spc + 1)));
}
Arrays.sort(f);
for (int i = 0; i < M; i++) {
P[i] = f[i].getPrice();
A[i] = f[i].getInventory();
}
int sum = 0;
int units = 0;
int a;
for (int i = 0; units < N; i++) {
if (A[i] <= N - units) {
sum = sum + P[i] * A[i];
units += A[i];
} else {
a = N - units;
if (a > A[i]) {
a = A[i];
}
sum = sum + P[i] * a;
units += a;
}
}
System.out.println(units);
System.out.println(sum);
w.println(sum);
w.close();
double endTime = System.currentTimeMillis();
System.out.println("Took " + ((endTime - startTime) / 1000) + " seconds.");
}
}
class Farmer implements Comparable<Farmer> {
private int price;
private int inventory;
public Farmer(int price, int inventory) {
this.price = price;
this.inventory = inventory;
}
public int getPrice() {
return price;
}
public int getInventory() {
return inventory;
}
#Override
public int compareTo(Farmer f1) {
if (f1.price != this.price) {
return this.price - f1.price;
} else if (f1.inventory != this.inventory) {
return f1.inventory - this.inventory;
} else {
return 0;
}
}
}
Java is an Object-Oriented language. Use it.
Your code keeps processing String lines, splitting and concatenating. That is slow.
Read your lines into objects containing the two integer values. Make the class implement Comparable, to sort by the two values, so you can call sort().
The processing is faster because you only parse the numbers once. The sorting is faster because you don't have to zero-pad the numbers, and you sort by integers, not string.
Since your lines consist of two integers separated by a single space, don't use split(). Use indexOf(' ') and call substring() twice. It's faster and less memory intensive.
I have just finished up computing the average cost of an OBST and I know I computed it correctly. My next task is to print the tree in preorder. I have an attempt at this using recursion but can't seem to shake the null pointer error.
Here's my code:
public class OBST {
static String[] keysA;
static Integer[][] root;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int tot = sc.nextInt();
HashMap<String, Double> hm = new HashMap<String, Double>();
int uniqNum = 0;
String[] rawInput = new String[tot];
for(int i=0; i<tot; i++) {
String tmp1 = sc.next();
if(i==0) {
hm.put(tmp1, 1.0);
uniqNum += 1.0;
} else if( i != 0) {
if(!hm.containsKey(tmp1)) {
hm.put(tmp1, 1.0);
uniqNum += 1.0;
} else {
Double tmpfreq = 0.0;
tmpfreq = hm.get(tmp1);
hm.put(tmp1, (tmpfreq + 1.0));
}
}
}
Set<String> keys = hm.keySet();
keysA = keys.toArray(new String[uniqNum]);
Double[] freqsA = new Double[uniqNum];
Arrays.sort(keysA);
for(int i=0; i<uniqNum; i++) {
Double tmp = 0.0;
String tmpK = keysA[i];
tmp = hm.get(tmpK);
tmp = tmp/tot;
freqsA[i] = tmp;
}
Double[][] eee = new Double[uniqNum+2][uniqNum+1];
Double[][] www = new Double[uniqNum+2][uniqNum+1];
//matrix to store optimal structure
root = new Integer[uniqNum+1][uniqNum+1];
for(int i=1; i<uniqNum+2; i++) {
eee[i][i-1] = 0.0;
www[i][i-1] = 0.0;
}
for(int l=1; l<uniqNum+1; l++) {
for(int i=1; i<=uniqNum-l+1; i++) {
int j = i + l - 1;
eee[i][j] = Double.MAX_VALUE;
www[i][j] = www[i][j-1] + freqsA[j-1];
for(int r=i; r<=j; r++) {
Double t = eee[i][r-1] + eee[r+1][j] + www[i][j];
if(t<eee[i][j]) {
eee[i][j] = t;
root[i][j] = r-1;
}
}
}
}
//total cost
System.out.println(eee[1][uniqNum]);
printTree(1,uniqNum-1,-1, "");
}
public static void printTree(int min, int max, int parent, String s) {
int r = root[min][max];
if(parent == -1 ) {
System.out.println(keysA[r] + " is root");
} else if(min < parent) {
System.out.println(keysA[r] + " is the left child of " + s);
} else {
System.out.println(keysA[r] + " is the right child of " + s);
} if(min < max) {
printTree(min,r,r+1,keysA[r]);
printTree(r+1,max,r,keysA[r]);
}
}
}
My trouble is in the method print tree.
Looks like you aren't checking your bounds correctly. If there is no left or right child, you shouldn't be printing that side. so make sure you check that r+1 is within the array size, and also that a node exists there. do the same for both left and right sides.