Binary search tree object creation issue - java

It's my first question here so apologies in advance if i miss any guideline.
i am working on binary search tree for learning purpose for past 3 days and i am stuck with one issue for a day now. tried to debug it as much as i can. Also tried to search on internet to see if there is any help but no success.
i have 3 classes
main class
bst class
integerset class
integerset has this constructor
public IntegerSet(int arr[])
{
this.bst1 = new BST();
for (int i = 0; i < arr.length; i++) {
this.bst1.insert(arr[i]);
this.magnitude = this.bst1.getSize();
}
}
which create bst object and insert array elements to bst.
when i do this from main
int[] arr = {1,2,3,4,5};
iSet = new IntegerSet(arr);
it works all fine, but when i create another object
int[] arr2 = {4,5,6,7};
iSet2 = new IntegerSet(arr2);
after creation of 2nd object both has same bst in them which contains 2nd array.
been trying to solve this but doesn't understand why this is happening both should have their own integer-set object with their own bst.

Do check implementation of IntegerSet. It should be like this:
class IntegerSet {
private final BST bst = new BST();
private int magnitude;
public IntegerSet(int[] arr) {
for(int val : arr)
bst.insert(val);
magnitude = bst.getSize();
}
}

Related

How can I create java array[][] using undefined number of arrays[]

Just out of curiosity, based on that code is there a way to that instead of
int [][]d = { obj[0].ar , obj[1].ar , obj[2].ar };
can be written under a for like this
for(int i=0;i<obj.ar.length;i++)
or to just combine all arrays of obj[].ar using obj.length in one 2 dimenstional array?
public class Main
{
public static void main(String[] args)
{
int nb = 3;
arr[] obj = new arr[nb];
for(int i=0;i<obj.length;i++)
{
obj[i] = new arr(i+2);
}
int [][]d = { obj[0].ar , obj[1].ar , obj[2].ar };
for(int i=0;i<d.length;i++)
{
for(int j=0;j<d[i].length;j++)
System.out.print(d[i][j]+"\t");
System.out.println();
}
}
}
class arr
{
int []ar;
arr(int nb)
{
ar = new int[nb];
for(int i=0;i<ar.length;i++)
ar[i]=i;
}
}
Java arrays must always have a determined size upon creation.
Notice you are always setting nb in the calls to new arrays, or by using the {} instantiator which will count the number of objects statically.
What you are asking for is probably what ArrayList is meant to achieve. It will grow as you go, while having an array implementation behind the scenes. If the contents cannot fit in the array, a new - larger - array is created to fit them all. You won't notice this while using it though.
ArrayList<ArrayList<Integer>> obj = new ArrayList<>();
obj.add(new ArrayList<>());
obj.add(new ArrayList<>());
obj.add(new ArrayList<>());
// There are now three empty lists, in the main list.
Since java 9, you can use some extra helper methods:
List<List<Integer>> obj = List.of(
List.of(1,2,3),
List.of(2,3,4)
);
If you want, you can implement you own ArrayList class, it's not that hard!

int[] vs ArrayList<>() in memoization, dynamic programming in Java

I recently watched a dynamic programming tutorial on Youtube explaining dynamic programming but the Tutor solved problems in JavaScript. I, on the other hand, use Java for data structures and algorithms. While implementing dynamic programming to solve a question. I discovered that I got the solution to the problem when using int[] but had wrong answer when using ArrayList<Integer> because somehow, the ArrayList already stored in the HashMap was being modified internally.
Question:
Write a function bestSum(targetSum, numbers) that takes in a targetSum and an array of numbers as arguments and returns an array containing the shortest combination of numbers that add up to exactly the target sum.
Example:
bestSum(7,new int[]{2,1,3}) => [3,3,1] //other possibilities but not answer:[2,2,2,1], [1,1,1,1,1,1,1], [2,2,1,1,1], etc
bestSum(100,new int[]{2,5,25}) => [25,25,25,25]
Code using int[]:
public class Persist {
public static HashMap<Integer,int[]> memo = new HashMap<>();
public static int[] bestSum(int n, int[] arr){
if(memo.containsKey(n)){
//System.out.printf("From memo: %d->"+ Arrays.toString(memo.get(n)) +"%n",n);
return memo.get(n);
}
if(n==0)return new int[0];
if(n<0)return null;
int[] minn = null;
for(int i = 0;i<arr.length;i++){
//recursion
var temp = bestSum(n-arr[i],arr);
if(temp!=null){
// ttemp is used to add arr[i] to the initial arr <<temp>>
int[] ttemp = new int[temp.length+1];
System.arraycopy(temp,0,ttemp,0,temp.length);
ttemp[temp.length] = arr[i];
temp = ttemp;
if(minn==null||temp.length<minn.length){
minn = temp;
}
}
}
//System.out.println(n+": "+minn);
memo.put(n,minn);
//System.out.println(memo.get(n));
return minn;
}
public static void main(String[] args){
System.out.println(Arrays.toString(bestSum(7, new int[]{2,1,3})));
}
}
Code using ArrayList<Integer> :
public class Persist {
public static HashMap<Integer,ArrayList<Integer>> memo = new HashMap<>();
public static ArrayList<Integer> bestSum(int n, int[] arr){
if(memo.containsKey(n)){
//System.out.printf("From memo: %d->"+ memo.get(n)+"%n",n);
return memo.get(n);
}
if(n==0)return new ArrayList<>();
if(n<0)return null;
ArrayList<Integer> minn = null;
for(int i = 0;i<arr.length;i++){
var temp = bestSum(n-arr[i],arr);
if(temp!=null){
temp.add(arr[i]);
if(minn==null||temp.size()<minn.size()){
minn = temp;
}
}
}
//System.out.println(n+": "+minn);
memo.put(n,minn);
//System.out.println(memo.get(n));
return minn;
}
public static void main(String[] args){
System.out.println(bestSum(7,new int[]{2,1,3}));
}
}
The only differences between the two code snippets is the use of int[] and ArrayList<Integer> respectively, but one works and the other doesn't. I will like to know why, thanks.
Link to Youtube explanation of bestSum()
It's easy to get caught up with memoization and dynamic programming and forget that about pass by reference and pass by value. The key difference here to remember is that ArrayList is pass by reference.
If you debug and look at your hashmap memo, you see that the sizes of the int[] only reaches up to 3, whereas in the arraylist hashmap most of the values has a size of 7
I had a similar problem: casting does not work on nested list object type and returns empty lists (List<List<Integer>>)

creating arrays within ArrayList java

I'm trying to create two different types of Arrays within one ArrayList. Set up constructors accordingly (I think), but when it comes to instantiating them I get an error message "arr cannot be resolved". I'm slowly but surely going round the bend. How do I get the ArrayList to accept a simple array with doubles? (It also has to accept other types so it's not just a question of changing the ArrayList itself).Here's the code for the constructors & main ArrayList:
class NumList implements Num
{
private ArrayList<Num> n1;
public NumList( NumDouble[] doubleArray )
{
n1 = new ArrayList<Num>();
for( NumDouble d : doubleArray )
n1.add( d );
}
public NumList(NumFloat[] floatArray )
{
n1 = new ArrayList<Num>();
for( NumFloat d : floatArray )
n1.add( d );
}
// methods of Num interface
}
And my test class looks like this -
import java.util.ArrayList;
public class Demo extends NumList {
public Demo(NumDouble[] doubleArray) {
//suggested automatically to add super here
super(doubleArray);
double[] arr = {(1.1), (2.2), (3.3), (4.4)};
ArrayList<Num> n1 = new ArrayList<Num>(arr);
}
public static void main (String [] args){
arr.sqrt();
System.out.println("The numbers sq are "+ arr [0]);
}
}
The NumList class has just three methods including sort. I have tried wildcards as well as
It's probably something really easy ... any help appreciated.
Your ArrayList holds object of type Num, but you are trying to insert plain ol' doubles into it
double[] arr = {(1.1), (2.2), (3.3), (4.4)};
ArrayList<Num> n1 = new ArrayList<Num>(arr);
double does not inherit from Num and so cannot be placed in an ArrayList<Num>. Also, no ArrayList constructor takes an array as a parameter, you have to convert your array to a collection with Arrays.asList(array). You would have to do something like this
NumDouble[] arr = {new NumDouble(1.1), new NumDouble(2.2), new NumDouble(3.3), new NumDouble(4.4)};
ArrayList<Num> n1 = new ArrayList<Num>(Arrays.asList(arr));

how to put a list of numbers from a file into an array and return the array

In this method I am trying to create an array from a file I passed into the method (the file has a list of numbers) and then I want to return the array. But when I try to run my code the error pops up that it can't find the symbol "nums".
I'm positive I have a scope problem, but I do not know how to fix this.
How do I fix this code so that it will return the array correctly?
Here is my code:
//reads the numbers in the file and returns as an array
public static int [] listNumbers(Scanner input) {
while (input.hasNext()) {
int[] nums = new int[input.nextInt()];
}
return nums;
}
You have at least two problems here.
Firstly, nums is defined inside your while loop, and it goes out of scope when you exit the loop. This is the cause of your compilation error. You'd need to move the definition outside of your loop if you want to return it once the loop has finished.
However, there's another problem, which is that you don't know how big your array needs to be until you've read the whole file. It would be much easier to create an ArrayList<Integer> and add elements to it, and then convert this to an array (if necessary) once you've read the whole file. Or just return the list, rather than an array.
public static List<Integer> listNumbers(Scanner input) {
List<Integer> nums = new ArrayList<Integer>();
while (input.hasNext()) {
nums.add(input.nextInt());
}
return nums;
}
List<Integer> list = new ArrayList<Integer>();
while(input.hasNext())
{
list.add(input.nextInt());
}
int size = list.size();
int[] nums = new int[size];
int counter = 0;
for(Integer myInt : list)
{
nums[counter++] = myInt;
}
return nums;
This solution is not tested, but can give you some direction. It's also along the lines of what Simon is referring to as well.

Simple Java objects not deeply copying

This question should be rather easy for any Java developer. I swear I looked it up after spending ~2 hours on it, but I can't really understand what's wrong with this code.
Basically, I am implementing Karger's minimum cuts algorithm. It requires me to keep merging nodes in a graph and then compute the number of crossing edges at the end (an int value). This algorithm must be repeated n times, always from the starting graph. My problem is that I am unable to create a deep copy of my Graph object, and I can't find the mistake.
I have cropped the code to just show the problem and no more, but I am still unable to figure out what's wrong. Here the code is.
Class Node:
public class Node {
public Integer Data;
public Node() {
Data = 0;
}
public Node(Node rhs) {
Data = rhs.Data.intValue();
}
public Node(Integer rhs) {
Data = rhs.intValue();
}
public void setNode(Integer rhs) {
Data = rhs;
}
Class Graph:
public class Graph {
public ArrayList<ArrayList<Node>> AdjList;
public ArrayList<Node> NodeSet; // This contains all the nodes
public Graph() {
AdjList = new ArrayList<ArrayList<Node>>();
NodeSet = new ArrayList<Node>();
}
public Graph(Graph G) {
AdjList = new ArrayList<ArrayList<Node>>();
for (ArrayList<Node> L : G.AdjList) {
ArrayList<Node> Lcopy = new ArrayList<Node>();
for (Node N : L) {
Node copy = new Node(N);
Lcopy.add(copy);
}
AdjList.add(L);
}
}
public void addNewAdjList(ArrayList<Node> NodeAdjList) {
// Input is the adjacency list of a new node
// The first element in the NodeAdjList is the node itself, the rest is the adj nodes
AdjList.add(NodeAdjList);
}
public static void printAdjList(ArrayList<Node> Adjlist) {
Node start = Adjlist.get(0);
System.out.print(start.Data + " : ");
for (int j=1; j < Adjlist.size(); ++j) {
System.out.print(Adjlist.get(j).Data + ", ");
}
System.out.print("\n");
}
Main:
public class Main {
/**
* #param args
*/
public static void main(String[] args) {
Node Five = new Node(5);
Node Seven = new Node(7);
Node One = new Node(1);
Graph G = new Graph();
ArrayList<Node> L = new ArrayList<Node>();
L.add(Five);
L.add(Seven);
L.add(One);
G.addNewAdjList(L);
Graph R = new Graph(G);
R.AdjList.get(0).get(1).setNode(19); // Gets node #1 in the first adj list, i.e. 7
Graph.printAdjList(G.AdjList.get(0));
Graph.printAdjList(R.AdjList.get(0));
}
}
Output:
5 : 19, 1,
5 : 19, 1,
This kind of puzzles me to be honest. I understand that Java is pass by value only, but objects are always represented by their reference. As far as I understand, my copy constructor for G should always make a deep copy: I am moving through every adjacency list and then I am making a deep copy of the Node. I don't understand why invoking .setNode() on the copied object modifies also the original object (that has a different reference).
Previous answers like 1 seem to go the same direction I am going, what am I missing here? :S
Your error is here:
ArrayList<Node> Lcopy = new ArrayList<Node>();
for (Node N : L) {
Node copy = new Node(N);
Lcopy.add(copy);
}
AdjList.add(L);
You created a copy of L (called Lcopy) but then you added the original L to your cloned graph. To fix it the last line should be this:
AdjList.add(Lcopy);
Note: If you have used a sensible name for your variable instead of L this error would probably never have happened!

Categories