Java initialize large array with Max value - java

How can I initialize an array of size 1000 * 1000 * 1000 * 1000 of all Integer.MAXVALUE?
for example, I want to make this int[][][][]dp = new int [1000][1000][1000][1000]; all have max value as later I need to compare a minimum.
I tried
int [] arr = new int arr[N];
Arrays.fill(arr,Integer.MAXVALUE);
but it doesn't work with multidimensional arrays, can anyone help?

You'll have to do this to fill your multi-dimensional array:
for (int i = 0; i < dp.length; i++) {
for (int j = 0; j < dp[i].length; j++) {
for (int k = 0; k < dp[j].length; k++) {
Arrays.fill(dp[i][j][k], Integer.MAX_VALUE);
}
}
}
You won't however be able to initialize new int[1000][1000][1000][1000] unless you have at least 3.64 terabytes of memory. Not to mention how long that would take if you did have that much memory.

You need something very specialized like Colt to generate what is called a Sparse Matrix. You need to alter your logic slightly, instead of testing against a Integer.MAX_VALUE you test to see if something exists at a location ( defaults to ZERO ), if it doesn't then consider it Integer.MAX_VALUE and leave it alone.
This assumes you only insert a fraction of the possible data with values < Integer.MAX_VALUE.

fill will need as arguments the array and the values to fill per dimension. Say fill(array, 0,0,0) or in your case fill(array, maxValue, maxValue, maxValue).
Cheers,

Related

Adding all indexes of arrays to one single array

I was wondering if this is the most efficient or even good code practice to add arrays to a single array as far as my knowllage goes its time would be O(n). This is only for practice and I want to do it for int [] not for the code to be changed so it is a List.
static int[] allArrayDirections(int row[], int col [], int diag []) {
int counter = 0;
int allDirectionsInMatrix [] = new int [row.length + col.length + diag.length];
for(int i = 0; i < row.length; i++) {
allDirectionsInMatrix[counter++] = row[i];
}
for(int j = 0; j < col.length; j++) {
allDirectionsInMatrix[counter++] = col[j];
}
for(int i = 0; i < diag.length; i++) {
allDirectionsInMatrix[counter++] = diag[i];
}
return allDirectionsInMatrix;
}
You could compare your linear solution to a sort of unravelled:
Find the longest of the three arrays, take its length as counter boundary
assign the longest array to a new variable first, the other two to second and third – just fiddling with the references so the for looks straightforward
loop once from 0 to the counter boundary
fill your target array in three steps, using the other array's length as offset – unless the smaller arrays are already exhausted, so skip them
This will need some add operation for the offset calculation to write to allDirectionsInMatrix and two greater then checks. Depending on the VM's optimization/ array lengths/ call frequency this might cut it in half.
The single for-loop looks similar to this:
// assuming first.length >= second.length >= third.length;
for(int i=0;i<largestLength;i++) {
allDirectionsInMatrix[i]=first[i];
if (second.length > i)
allDirectionsInMatrix[i+first.length]=second[i];
// I assume when called often enough VM does auto trickery
// with the repeated addition of i and first.length
if (third.length > i)
allDirectionsInMatrix[i+first.length+second.length]=third[i];
}
But this might also break other VM optimizations when treating the arrays independently. So really compare runtime. I'd appreciate to read about your measurements.
Just FYI (and not a reals answer to your question, but maybe interesting for comparison)
One way to concatenate integer arrays (using Streams) would be
int[] a = {1,2,3};
int[] b = {4,5,6,7};
int[] c = IntStream.concat(Arrays.stream(a), Arrays.stream(b)).toArray();
System.out.println(Arrays.toString(c));
(Stream.concat for arrays of other types)

Putting an array into a bigger array

I have an array of terms (terms meaning an object with a coefficient and a degree, represented as for example 1.0x^6). The array that I have right now contains 3 terms:
[1.0x^6, 4.0x^5, 10.0x^0].
My goal is to create a bigger array with these terms, but ALSO with terms with a 0 coefficient that are not represented in my array. That probably was not too clear, so here is basically what I want my new array to look like:
[1.0x^6, 4.0x^5, 0.0x^4, 0.0x^3, 0.0x^2, 0.0x^1, 10.0x^0].
Currently, I am iterating through my original array, and if the degree equals the new array.length - 1, I am setting newArray[i] = array[i], if that makes sense. For example, for the first term and i = 0, the degree is 6, and so if 6 = newArray.length - 1 (which is 6), then newArray[i] = array[i].
The problem, however is that array is smaller than newArray, so I am getting an out of bounds error. Any ideas on how to fix this? Sorry for the long post, thanks!
EDIT: Here is my actual code. Sorry if the explanation was unclear.
int max = 0;
Term temp;
for(int i=0; i<array.length; i++) {
max = i;
for(int j=i; j< array.length; j++) {
if(array[j].getDegree() > array[max].getDegree()) {
max = j;
}
}
temp = array[i];
array[i] = array[max];
array[max] = temp;
}
Above, the array is sorted in terms of descending degree. I want to now have the new array contain the old terms, but also 0x^i for all the i that are not used in my set of terms.
Term[] newArray = new Term[this.degree()+1];
for (int c = 0; c < newArray.length; c++) {
if (array[c].getDegree()==newArray.length-1-c) {
newArray[c] = array[c];
}
else {
newArray[c] = new Term(0, newArray.length-1-c);
}
}
There are issues in my code above, and I can see that now because in that for loop, array[c] is not defined for any c > 2. Eclipse is telling my that I have an out of bounds error.
Arrays have a fixed size. If you want to create a bigger array, you need to know the size beforehand and define it accordingly. Also, it seems that you are going through both the arrays using the same iteration variable.
I assume you are doing something like this:
for(i=0;i<newArray.length;i++){
newArray[i] = array[i]; //size of newArray is bigger than array
}
Then you will always get an array index out of bounds exception because "array" is smaller than "newArray" and you go out of bounds when i>=array.length.
You need to fix your code logic.

Performant way to select N random distinct ints in java?

I currently am looking for the best way so select x unique ints among a range of n ints. It would be like doing Random.nextInt(range) multiple time except it should never select twice the same int.
If it happens that x > n then the result would only contain n ints
I tried to do this myself and I currently have done this based on the Fisher/Yates shuffle:
private static final Random R = new Random();
public static int[] distinctRandoms(int nb, int max) {
int[] all = new int[max];
for (int i = 0; i < all.length; i++) {
all[i] = i;
}
if (max <= nb) {
return all;
}
int index;
int[] result = new int[nb];
for (int j = 0, k = all.length - 1; k > 0 && j < nb; k--, j++) {
index = R.nextInt(k + 1);
result[j] = all[index]; // save element
all[index] = all[k]; // overwrite chosen with last element
}
return result;
}
It works and performance seems good but I can't help thinking there must still be some more performant way to do so and that i'm reinventing the wheel. I thought about doing things differently if nb > (max / 2) (remove elements rather than select elements) but as you can't truncate an array in java you still end up copying all the elements you need.
This method costs alot if nb = max-1
Is there any built in way to randomly select distinct ints efficiently in java ?
Edit 1:
What I mean by performant is time-efficient. I want it to be fast. I'll mostly work with small sets of randoms.
Edit 2:
I tried using shuffle like that but it's much more expensive in terms of time because of all the extra object creation.
public static Integer[] distinctRandoms2(int nb, int max) {
ArrayList<Integer> all = new ArrayList<Integer>(max);
for (int i = 0; i < max; i++) {
all.add(i);
}
if (max <= nb) {
return all.toArray(new Integer[max]);
}
Collections.shuffle(all);
return all.subList(0, nb).toArray(new Integer[nb]);
}
You can use Floyd's algorithm. It is much more efficient than shuffling if the number of elements to be selected is smaller than their range.
private static final Random random = new Random();
/**
* Converts a set of Integer to an array of int.
*/
private static int[] setToArray(Set<Integer> aSet) {
int[] result = new int[aSet.size()];
int index = 0;
for (int number : aSet) {
result[index] = number;
index++;
}
return result;
}
/**
* Generates an array of min(count, maxValue) distinct random ints
* from [0, maxValue - 1] range.
* #param count The number of elements to be generated.
* #param maxValue The upper bound of the range(exclusively).
*/
public static int[] getDistinctRandomNumbers(int count, int maxValue) {
Set<Integer> was = new HashSet<>();
for (int i = Math.max(0, maxValue - count); i < maxValue; i++) {
int curr = i == 0 ? 0 : random.nextInt(i);
if (was.contains(curr))
curr = i;
was.add(curr);
}
return setToArray(was);
}
It has O(count) time and space complexity, where count is number of distinct integers that should be generated.
You can use shuffle method from java.util.Collections class.
Just create list of Integers from 0 to x-1, then call shuffle method on it and take first nb elements.
Using shuffle method has sense when nb is close to max. So it would be good for following pairs of parameters:
nb=70, max=100
nb=900, max=1000
nb=9000, max=10000
but not so good for:
nb=10, max=10^8
nb=100, max=10^9
It would be a good idea to combine above method (using shuffle) with Floyd's algorithm from other answer. Selection of algorithm should be based on ratio nb/max. Border ratio should be chosen carefully.
It depends on what you mean by Performant and Random.
If you really are in need of something that costs O(1) or similar then you could use a Linear feedback shift register or LFSR. It generates a random-like sequence of numbers (i.e. statistically random but theoretically predictable) using a simple XOR operation on the previous number and is thus probably the fastest mechanism possible.
This approach is most appropriate if you want any n-bit number. Limiting the number range by discarding those outside the required range may reduce performance.
If by "small sets of randoms" you mean that max is small, the Collections#shuffle approach is probably as good as you can get.
If max can be arbitrary large but nb is small then using a HashSet may be your best option, although you will have some boxing/unboxign cost. If you want to avoid that cost, you can try using an IntHashSet or a similar primitive specialisation of HashSet.

Adding each value to an integer array

Can you help me with my problem? I need to add values to my int array but all I get is an ArrayIndexOutOfBoundsException.
public static void numberSort(){
int quantity = 0;
int[] values = new int[quantity];
int allocate = 0;
quantity = Integer.parseInt(JOptionPane.showInputDialog("How many values do you wish to sort? : "));
for(int x = 0; x <= values.length; x++){
allocate = Integer.parseInt(JOptionPane.showInputDialog("Values you want to sort : "));
values[allocate] = x;
System.out.println(values[x]);
}
int quantity = 0;
int[] values = new int[quantity];
You're allocating an array with 0 locations, which is effectively a zero-length array. This means that it really doesn't have any valid locations, so you can't store anything into it. This is why you're getting an ArrayIndexOutOfBounds exception when you attempt to store anything inside the array.
You will have to move the line where you allocate values to the line after the line where you read in the value of quantity.
Your next problem is your for loop:
for(int x = 0; x <= values.length; x++)
Array indices run from 0 to array.length - 1. So typically the terminating condition for the for loop is x < values.length. If this was your code, you wouldn't have seen this exception. However, even if you fix this to make quantity a non-zero value, you will get the exception when you attempt to fill the array since values[array.length] is out of bounds. So you will have to change your for loop to:
for(int x = 0; x < values.length; x++)
I also noticed that you have values[allocate] = x;. What you want is values[x] = allocate;, since you want the xth element of the array.
This line is your problem
int quantity = 0;
int[] values = new int[quantity];
You are creating an array with length 0. The length of an array is established when the array is created. After creation, its length is fixed.
Read more in tutorials: Arrays
For quick fix in your code just init your array after quantity
int quantity = Integer.parseInt(JOptionPane.showInputDialog("How many values do you wish to sort? : "));
int[] values = new int[quantity];
And in for loop change <= to < cause arrays starts in 0.
for(int x = 0; x < values.length; x++){
allocate = ...
values[x] = allocate; // you want to allocate in position "x" allocate
}
Aside from creating an array of 0 length, your for loop end condition is incorrect. You wrote x <= values.length, but you should write x < values.length. Since arrays in Java are 0-indexed, that means the valid range of indices are 0 to values.length - 1.
I count three errors in there. The most significant one:
for(int x = 0; x <= values.length; x++){
Java arrays index from zero - that means that for example an array with length of 5 has indexes 0, 1, 2, 3 and 4. Anything beyond that in either direction results in the ArrayIndexOutOfBoundsException. Because you use <=, you read one value beyond what's allowed. Replace it with <.
Also, you initialize your array to size zero. That means you can't really use it. Initialize your array with quantity only once quantity has the correct value!
Finally, I believe you want values[x] = allocate;, not vice versa.

Sqrt, and Math in Arrays

I'm having difficulty understand how to write this array. I need it to out-print 10x5 (50 elements total), and have the first 25 elements equal to the sqrt of the index that it is in, and the last 25 to equal 3 * the index. Yes, this is homework but I'm not asking for you to do it for me, I just need help! I'm getting errors when using Math saying that I cant use double and the double array together. Here is what I have so far:
public class snhu4 {
public static void main(String args[]) {
double alpha[][] = new double[10][5];
double[] sum, sum2;
for (int count=0; count<=25;count++) {
alpha[count]= Math.sqrt(count);
}
for (int count=26; count<=50;count++) {
alpha[count]= count *3;
}
for (int count=0; count<=50;count++) {
System.out.print(alpha[count]);
}
}
}
Because alpha is a multidimensional array, you can't refer to its elements like a normal array.
int myarray[][] = new int[2][2];
In the above example, the array myarray is multidimensional. If I wanted to access the second element in the first array, I would access it like this:
int myint = myarray[0][1];
You are trying to access a multidimensional array by using the access for a normal array. Change
alpha[count]
to
alpha[0][count]
or similar.
Read here for more information on multidimensional arrays.
you defined alpha as a 2D array with lets say 10 items in the first dimension and 5 in the second, and 5x10 is 50 elements.
When using your array to assign values to these elements, u must call upon the array using 2 indices, one for each dimension:
alpha[i][j] = /*double value*/; //with 0<=i<=9 and 0<=j<=4
So the first 25 elements going from left to right in dimension order is going to be:
[0to9][0] and [0to9][1] and [0to4][2]
the next 25 will be
[4to9][2] and [0to9][3] and [0to9][4]
from then on i cannot give you the answers to your homework, but the loops should look like this:
int j;
for(int i = 0; i<25; i++)
{
j=i/10; //integer division will return 0 for i<10, 1 for 10<i<20, etc..
alpha[i%10][j] = Math.sqrt(i);
}
and you can figure out the rest
The 10x5 appears to be an output constraint, not a design constraint.
You are using Java, so use Java constructs, not C-language constructs;
specifically store the values in a List not an array.
Here are some hints:
List<Integer> valuesList = new ArrayList<Integer>();
for (int index = 0; index < 25; ++index)
Integer currentValue = Math.sqrt(index);
valuesList.add(currentValue);
for (int index = 25; index < 50; ++index)
Integer currentValue = index * 3;
valuesList.add(currentValue)
int count = 1;
for (Integer current : valuesList)
if ((count % 5) == 0) // write a newline.
System.out.print(current);
++count

Categories