Subset Generator gives out java heap space error - java

Here are the errors I receive when running the tester class. I keep looking at where the code is pointing but I don't see where the issue is. It keeps saying I am also out of Java heap space, not sure what that is. I also am not sure if my recursive getsubset() method is even working correctly, as I can't even compile my tester class. If there are any other mistakes in my code be free to point them out. Thank you!
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOfRange(Arrays.java:3209)
at java.lang.String.<init>(String.java:215)
at java.lang.StringBuilder.toString(StringBuilder.java:430)
at SubsetGenerator.getSubsets(SubsetGenerator.java:68)
at SubsetGenerator.getSubsets(SubsetGenerator.java:64)
at SubsetGeneratorTester2.main(SubsetGeneratorTester2.java:23)
Press any key to continue...
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
Prints subsets of String
*/
public class SubsetGenerator
{
private String word="";
private ArrayList<String> subsets;
/**
Constructs a word to generate subsets from
#param text input by user
*/
public SubsetGenerator(String textinput)
{
word=textinput;
subsets = new ArrayList<String>();
}
/**
retrieves word
#return the word
*/
public String getWord()
{
return word;
}
/**
get subsets
#return subset arraylist
*/
public ArrayList<String> getSubsets()
{
if(word.length() == 1)
{
subsets.add(word);
return subsets;
}
else
{
String removed = word.substring(0,1);
word = word.substring(1);
getSubsets();
for (int i = 0; i < subsets.size(); i++)
{
String temp = removed + subsets.get(i);
subsets.add(temp);
}
subsets.add(removed);
return subsets;
}
}
//sort subsets
public void sortSubsets()
{
Collections.sort(subsets);
}
}
import java.util.Collections;
import java.util.ArrayList;
import java.util.List;
/**
This program tests the subset generator.
*/
public class SubsetGeneratorTester2
{
public static void main(String[] args)
{
SubsetGenerator generator = new SubsetGenerator("rum");
List<String> subsets = generator.getSubsets();
// Sort the result for checking
Collections.sort(subsets);
System.out.println(subsets);
System.out.println("Expected: [, m, r, rm, ru, rum, u, um]");
}
}

The problem appears to be with the loop. If its not empty, an element is added so the size increases. Then since an element was empty, i+1 cannot ever be greater than or equal to the new size. This will very easily exhaust the heap. This fails however on the empty string with a runtime error immediately.
I can confirm that the loop is the culprit. Fixed this by simply moving the index out of the loop. That way it won't update as elements are added.
int size = subsets.size();
for (int i = 0; i < size; i++)
{
String temp = removed + subsets.get(i);
subsets.add(temp);
}
However, there was another issue.
Your method resulted in the set:
[m, r, rm, ru, rum, u, um]
This was easily changeable, since your base case was wrong. I also didn't want to modify too much of the code (but there is a better way to do this!)
In your example, the empty string would never work, however logically it should. The way I would handle this, is as follows (in pseudo code):
List subset(String str):
if(length == 0):
return [""];
x = subset(str.substring(1));
result = [];
for s in x:
result += [s, str.charAt(0) + s];
return result;
This of course is pseudo code (and close to python actually). I didn't want to give it all away, but the basic merit is to understand how these can be accomplished.
The important thing to note is that for each element, we add 2 strings to the list. One with the first character of the current string and one without the first character of the current string.
Consider some basic cases:
subset("") -> [""]
subset("a") -> ["", "a"]
subset("ab") -> ["", "a", "b", "ab"]
Hopefully you can see the pattern. For each string we add one with the character and one without.

I will give you another solution which is more clear than yours. First cut off a character from word. Then use that character to connect the remainder. Finally call getSubsets() recursively. If the word.length is zero, it reached the bottom and it will return.
public ArrayList<String> getSubsets(){
if(word.length()==0){
subsets.add("");
return subsets;
}
else{
String removed=word.substring(0,1);
word=word.substring(1);
subsets.add(removed);
for(int i=0;i<word.length();i++){
String temp=removed+word.substring(0,i+1);
subsets.add(temp);
}
}
getSubsets();
return subsets;
}
It's my anwser:
root#MQ-PC:/home/java/algorithm# java SubsetGenerator
[r, ru, rum, u, um, m, ]

Related

Java PriorityQueue with Custom Objects not Sorting Correctly [duplicate]

This question already has answers here:
Why does PriorityQueue.toString return the wrong element order? [duplicate]
(4 answers)
Closed 8 months ago.
I don't completely understand how to use a Java PriorityQueue (max Heap) for custom objects.
I'm working on a LeetCode problem where my code must reorder the words in a sentence by word length. My instinct was that I could use a PriorityQueue to do the work of word-ordering for me. To do that, I thought I could track words with a custom object:
public class word implements Comparable<word>{
public String theWord;
public int len, order;
public word(String w, int order) {
this.theWord = w;
this.order = order;
this.len = w.length();
}
#Override
public int compareTo(word o) {
return this.len - o.len; // sorting behavior controlled here, right???
}
public String toString() {
return this.theWord+"("+this.order+") "; // for troubleshooting
}
}
Then:
public String arrangeWords(String sentence) {
PriorityQueue<word> maxHeap = new PriorityQueue<>(Comparator.naturalOrder());
String[] words = sentence.split(" ");
for( int i=0; i<words.length; i++ ) {
maxHeap.offer( new word(words[i], i) );
}
}
The first sentence I'm using to test is "leetcode is cool". (From the LC post.)
The ordering I'm hoping for is: "is cool leetcode" (shortest-to-longest word order)
But when I run the above code and check the PriorityQueue in the debugger, I see:
is(1) leetcode(0) cool(2)
Sooo... what the heck? I don't understand how this is ordered at all. This is not the original order (indicated by parenthesis), not in length order, not even in alphabetical order. I have no idea how the PriorityQueue is deciding how to order the word objects. I thought that the class word's compareTo() method would force the ordering that I want. (I've seen this with other SO posts.) But not so. Does someone see what I'm going wrong? Thank you.
You inserted them in priority queue. But then you need to poll the queue to get the right order of words.
while (!maxHeap.isEmpty()) {
System.out.println(maxHeap.poll());
}
Also please note the order field won't get altered just because you inserted them in priority queue. It just shows the order in which the word appears in original sentence.
Write that loop after your for loop where you inserted. Then execute again. You will see right order.
PriorityQueue( minHeap) maintains that the top element is of the lowest length . The remaining elements will be in random order. Once you poll the top element, then re-ordering happens( upHeapify -technically ) that makes the smallest from the remaining to become the top element. As already pointed out, you need to poll all the objects and make them part of your sentence.
Also, another way to go about the problem was -> you could have simply used the comparator on the array of String.
class Solution {
public static String arrangeWords(String text) {
String str[] = text.split(" ");
Arrays.sort(str, (a, b) -> a.length() - b.length());
String res = "";
for ( int i = 0; i< str.length; i++)
{
if ( i ==0 )
{
res += str[i].substring(0,1).toUpperCase() + str[i].substring(1) + " ";
}
else{
res += str[i].substring(0,1).toLowerCase() + str[i].substring(1) + " ";
}
}
return res.trim();
}
}

print all the strings possible of length k from a given string with repition allowed usibg arraylist

Given a string S and an integer k, you need to find and return all the possible strings that can be made of size k using only characters present in string S.
The characters can repeat as many times as needed.
import java.util.*;
public class Solution {
public static String[] allStrings(String charSet, int len) {
// Write your code here
HashMap<Character,Boolean> map=new HashMap<>();
for (int i=0; i<charSet.length();i++){
if(!map.containsKey(charSet.charAt(i))){
map.put(charSet.charAt(i),true);
}
}
ArrayList<Character> al=new ArrayList<Character>();
for (Map.Entry<Character,Boolean> entry:map.entrySet()){
al.add(entry.getKey());
}
ArrayList<String> real=new ArrayList<String>();
String pre="";
perm(pre,al,len,real);
String []a=new String[real.size()];
a=real.toArray(a);
return a;
}
public static void perm(String pre,ArrayList<Character> al,int k,ArrayList<String> real) {
if(k==0){
real.add(pre);
return;
}
for(int i=0;i<al.size();i++){
pre=pre+al.get(i);
perm(pre,al,--k,real);
}
}
}
Here I am getting stack overflow error #
pre=pre+al.get(i);
perm(pre,al,--k,real);
You have two issues here:
pre=pre+al.get(i);
perm(pre,al,--k,real);
You make this recursive call al.size() times, and each time you decrement k. Since k is initialized to the length of the desired Strings, if k < al.size(), it will eventually become negative, and the recursive call will never terminate (since it terminates only when k==0).
Before each recursive call, you add a character to pre, but you don't remove the character added in the previous iteration. Therefore you'll end up with output Strings longer than the desired length.
You can fix the issues as follows but keeping pre and k unchanged:
public static void perm(String pre,ArrayList<Character> al,int k,ArrayList<String> real)
{
if(k==0){
real.add(pre);
return;
}
for(int i=0;i<al.size();i++){
perm(pre+al.get(i),al,k-1,real);
}
}

Sorting two dimensional String array as per LastName then on FirstName without using any API

Hi all I am very new for the Java. I would like to sort below array of strings as per LastName then on FirstName without use of any API i.e. I am not supposed to use Arrays.sort() , compareTo(), equals() etc..
Input array String
String [][]name={{"Jen","Eric"},
{"Brain","Adams"},
{"Jon","Methew"},
{"Antino","Ronald"},
{"Cris","Ronald"}
};
my out put should be like.
Brain,Adams
Jen,Eric
Jon,Methew
Antino,Ronald
Cris,Ronald
Please Help.
public class StringArraySort {
public static void main(String[] args) {
//System.out.println(str.length);
String [][]name={{"Jen","Eric"},
{"Brain","Adams"},
{"Jon","Methew"},
{"Antino","Ronald"},
{"Cris","Ronald"}
};
String []str1= new String [name.length];
String []str2= new String [name.length];
for(int i=1;i<name.length;i++)
{
int j=i;
str1[i]=name[i][j];
str2[i]=name[i-1][j];
//System.out.println(str1[i]+" "+str2[i]);
}
/*for(String tmp:name)
{
char a[] = new char[tmp.length()] ;
//System.out.println(tmp);
for(int i=0;i<tmp.length();i++)
{
a[i]=tmp.charAt(i);
System.out.println(a[i]);
}
}*/
}
}
I will not give you any code, as this is clearly an assignment, but here's some general guidance:
Don't try to put everything into main. You may not be allowed to use any exiting API, but you can define your own! Write your own compare and sort methods.
Start with a method compare(String, String) -> int, or isSmaller(String, String) -> boolean. Use String.toCharArray to get the individual characters and compare them, in pairs from both strings. Make sure to handle the case of the strings having different lengths.
Now write a method compare(String[], String[]) -> int. This can look very similar to the above (in fact, you could make a generic one for both), but it might be simpler to make this one specific for the "lastname-firstname" case, particularly since here you want to sort by the second element first.
Finally, write your own sort method. An in-place bubble sort should be the easiest and the algorithm can easily be found on the internet. Other sort algorithms are faster, but if speed is an issue, the requirement not to use any API is nonsensical in the first place. If you want to score bonus-points, though, you can try to implement an in-place quick sort, but only after you've got it running with the bubble sort.
Also, you should test each of those methods individually. Don't try to run your sort method before you've made sure your compare methods actually work. Call them individually with different outputs and see whether they yield the correct result.
public class NameSort {
public static void main(String[] args) {
String [][] names={{"Jen","Eric"},
{"Brain","Adams"},
{"Jon","Methew"},
{"Antino","Ronald"},
{"Cris","Ronald"}
};
for(int m=0;m<names.length;m++)
{
for(int n=m+1;n<names.length;n++)
{
if(myCompare(names[m][1],names[n][1])==1)
{
swap(names, names[m], names[n], m, n);
}
else if (myCompare(names[m][1],names[n][1])==0)
{
if(myCompare(names[m][0],names[n][0])==1)
{
swap(names, names[m], names[n], m, n);
}
}
}
}
for (int i=0;i<names.length;i++)
{
System.out.println(names[i][0]+" " +names[i][1] );
}
}
public static void swap(String [][] names,String[] a,String[] b,int m,int n)
{
names[n]=a;
names[m]=b;
}
public static int myCompare(String a, String b)
{
int minLength= a.length()<b.length()?a.length():b.length();
for(int i=0;i<minLength;i++)
{
if(a.charAt(i)>b.charAt(i))
{
return 1;
}
else if(a.charAt(i)<b.charAt(i)){
return -1;
}
}
if(a.length()>minLength)
return 1;
else if (b.length()> minLength )
return -1;
else
return 0;
}
}
In order to let you learn at least something, I am going to give you the answer in psuedo-code and let you do the coding. The solution is based on bubble sort and comparing names (=Strings) by looping on their characters
in bubble sort we iterate over the array, in each iteration, we compare two adjacent cells and possibly swap them so that they are in the correct order.
at the end of the 1st iteration, the biggest cell will be in the correct position (=last). so we start another iteration but skip the last cell. by the end of the 2nd iteration, the 2nd biggest cell will in its correct position. we cotinue iterating, each time going over one less cell until there are no more cells to iterate over.
I give you the comparing method:
The solution assumes you are allowed to call length() and charAt() methods of String class.
/**
* returns negative, zero or positive value
* if s1 is smaller, equal or bigger than s2, respectively
* comparison is lexicographical
*/
static int compareStrings(String s1, String s2)
{
int i = 0;
for (i = 0; i < s1.length() && i < s2.length(); i++) {
int diff = s1.charAt(i) - s2.charAt(i);
if (diff != 0) return diff;
}
if (i == s1.length()) {
if (i == s2.length()) return 0; // equal lengths
else return 1; // exhausted s2 before s1
}
return -1; // exhausted s1 before s2
}
seeing the loop in your code, I think one last note is in order: you should be aware that arrays in Java start with index 0 and the last cell is at length-1.

Find and print the product of all the entries in array

Okay I have tried to write a simple Java code in BlueJ, that finds and prints the product of all the entries in data such as if data is {1,2,3,4} then the result will be 24.
And my code is below:
public class Product {
public static int[] product(int[] a) {
int [] s = new int[a.length];
for (int i =0; i< a.length; i++)
s[i] = a[i]*a[i];
return s; //the definition of your method...
}
public static void main(String[] args) {
//calling the method to seek if compiles
int[] results = Product.product(new int[] { 1,2,3,4 });
//printing the results
System.out.println(java.util.Arrays.toString(results));
}
}
The above code is giving me the square of each number, which is not what I want to have, somehow I have modify the code that the result will be 24 but I couldn't figure it out, anyone knows how to do it?
First of all, if you are first writing Java it is important to know that variable, function and class names are quite important. Please note that having Product.product() is not a good idea, since the function name is almost the same as the class name. Anyway, regarding your code. Your code is indeed returning the square of your input, what you would want is the following:
public class Product {
public static int getProduct(int[] input) {
int total = 1;
for (int v : input) {
total *= v;
}
return total;
}
}
This will return an integer value with the product of your input array. This also uses a for-each loop instead of a regular for-loop for readability. Also you don't need the index in this case. Good luck with it!
First, your product method needs to return an int rather than an int [].
You need to maintain the product as a variable. You can set it to 1 initially, and then multiply it by each element of the a array in turn; then you just return this value.

Searching through an ArrayList

Implement a method
public void search (String searchString) { }
to iterate through the notes ArrayList until it
finds a note that contains the searchString.
It should then print either the item found or
the message "String not found".
So far, I have:
import java.util.ArrayList;
import java.util.Iterator;
/**
* A class to maintain an arbitrarily long list of notes.
* Notes are numbered for external reference by a human user.
* In this version, note numbers start at 0.
*
* #author David J. Barnes and Michael Kolling.
* #version 2008.03.30
*/
public class Notebook
{
// Storage for an arbitrary number of notes.
private ArrayList<String> notes;
/**
* Perform any initialization that is required for the
* notebook.
*/
public Notebook()
{
notes = new ArrayList<String>();
}
/**
* Store a new note into the notebook.
* #param note The note to be stored.
*/
public void storeNote(String note)
{
notes.add(note);
}
/**
* #return The number of notes currently in the notebook.
*/
public int numberOfNotes()
{
return notes.size();
}
/**
* Show a note.
* #param noteNumber The number of the note to be shown.
*/
public void showNote(int noteNumber)
{
if(noteNumber < 0) {
// This is not a valid note number, so do nothing.
System.out.println("invalid index given");
}
else if(noteNumber < numberOfNotes()) {
// This is a valid note number, so we can print it.
System.out.println(notes.get(noteNumber));
}
else {
System.out.println("there are fewer items in the notebook");
// This is not a valid note number, so do nothing.
}
}
public void removeNote(int noteNumber)
{
if(noteNumber < 0) {
// This is not a valid note number, so do nothing.
System.out.println("invalid index given");
}
else if(noteNumber < numberOfNotes()) {
// This is a valid note number.
notes.remove(noteNumber);
}
else {
System.out.println("there are fewer items in the notebook");
// This is not a valid note number, so do nothing.
}
}
/* Edit note.
* I tried to improve the formatting of the code below, but I'm completely
* unable to figure out how on earth anything of that should make sense
* and therefore the indentation is completely without any meaning.
*/
public void search (String searchString)
{
for each notes in ArrayList {
if notes = searchString;
System.out.println("String found"); + searchString
return end
}
if}
System.out.println("String not found");
}
}
But it is not working, and I am not able to work it out.
Several problems:
Your search method is actually outside the class.
The body of your search method makes no sense at all.
If you're counting on the monkeys writing Shakespeare, you'll be waiting a while.
To iterate over the array list, you can use a 'for-each' loop:
for (String note: notes) {
// Do something with note
}
This is very basic syntax. Have you seen it before? If not, you should start by reading a very basic tutorial to Java before attempting this homework.
Fundamentally you need to look at each item in your ArrayList and test to see if it matches the search condition. In Pseudocode
for each note in notes
{
if note equals searchString then
print "Found " + searchString
return
end if
}
print "not found"
Given that basic outline, want to take a second stab at coding it in Java?
Basically you want to loop over the elements, and for each one check whether it equals the element you are searching for. You can use a for loop or a foreach loop to do the actual iteration.
should you be checking if the whole note matches your searchstring, or if the note contains your searchstring?
i.e. given notes "foobar","baz","spam", should a search on "foo" return "foobar" or not match on anything?
so in pseudocode:
for each note in notes
{
if searchstring in note
{
print "Found :"+note
}
}
check this website http://pleac.sourceforge.net/pleac_java/arrays.html it may be useful

Categories