Let's say I have a two dimensional array defined as:
boolean[][] col = new boolean[8][3];
Now how would I go about accessing all 8 values from the first dimension from any of the 3 locations on the second dimension? For example, col[0] would do what I want, but reversed.
For further clarification, I need to know how to access one of the 3 arrays with 8 values in it, rather than one of the 8 arrays with 3 values in them.
While this isn't exactly what I was looking for, I have found a computationally slow and large solution:
boolean[] getA(int k) {
boolean[] buf = new boolean[8];
for(int i = 0; i < 8; i++) {
buf[i] = col[i][k];
}
return buf;
}
Related
Adding elements to an array in java ,given the size, is easy to code but doing it dynamically poses a problem .
Ex:
Int a[]= new Int[5];
a[0]=0;
a[1]=2;
a[2]=2;
a[3]=3;
a[4]=4;
Here(in the above example) we know the size, so I can assign the values. What If don't know how many values I have to add, in some cases it could be 5 and some other it might be 100.
So for such a situation I would need an array which will take input dynamically(as many as I input) or on spot.
My question is how to make an array dynamic in Java?
It could be done using List, but is there a way using array?
Please help me out
You can't allocate dynamically an array, but you can always create a new one when this one is full. This is a method to call when the array is full. it will return a new array with more elements and will get the elements from the old array:
public int[] createNewArray(int[] oldArray){
int[] newArray = new int[oldArray.length * 2];
for(int i = 0; i < oldArray.length; i++) {
newArray[i] = oldArray[i];
}
return newArray;
}
I'm trying to put a certain amount of integers into an array in random spots without putting them in the same place.
My combine method concatenates two given integers and returns the Int.
Places is an arrayList to keep the locations of the integers already put into the array.
The random method returns a random integer in between the two given ints.
The combine method works and so does the random method, but I'm not sure why it isn't working.
public void fillOne(int b)
{
for(int x = 0; x < b; x++)
{
int kachow = random(0, 5);
int kachigga = random(0, 5);
int skrrt = combine(kachow, kachigga);
if(notInArray(skrrt))
{
locations[kachow][kachigga] = 1;
places.add(skrrt);
}
}
}
You haven't really explained what isn't working. But an obvious flaw in your algorithm is that it isn't guaranteed to set b elements to 1. If your algorithm generates a duplicate position then it will set fewer than b elements.
Your logic for storing the combined positions is overly complex. One solution would be to reverse the logic: generate a single integer representing both dimensions then divide it into two when you are setting the location. That makes the checks a lot simpler.
For example, if your array is 5x5:
Set<Integer> positions = new HashSet<>();
while (positions.size() < n)
positions.add(random.nextInt(25));
for (int p: positions)
locations[p/5][p%5] = 1;
Because positions is a set it automatically excludes duplicates which means the code will keep adding random positions until their are n distinct positions in the set.
Even simpler, if you are using Java 8:
random.ints(0, 25)
.distinct().limit(n)
.forEach(p -> locations[p/5][p%5] = 1);
What is the best and efficient way to get the maximum i, which is the number of rows and j, which is the number of columns, in a two dimensional array?
Hopefully, the time complexity can be lower than O(n) for every case. No loop here and can still find the maximum j.
For example, if I have an array like this one
[
[18,18,19,19,20,22,22,24,25,26],
[1,2,3],
[0,0,0,0]
]
Then I want to get i = 3 and j = 10 here as a result.
Can anyone help me?
You can avoid writing the loop yourself, but you can't avoid having a runtime of at least O(n), since "someone" needs to loop the source array.
Here is a possible way to do that in Java 8:
Arrays.stream(arr).map(row -> row.length).max(Integer::compare).get();
This returns the maximum length of a "row" in your 2d array:
10
Another version which avoids using the Comparator and therefore might be a bit easier to read:
Arrays.stream(arr).mapToInt(row -> row.length).max().getAsInt();
arr is supposed to be your source array.
Edit: the older version used .max(Integer::max), which is wrong and causes wrong results. See this answer for an explanation.
Assuming your array does not contain null values, you could write something like this:
private static final Comparator<int[]> lengthComparator = new Comparator<int[]> () {
#Override
public int compare(int[] o1, int[] o2) {
return o1.length - o2.length;
}
};
#Test
public void soArrayMaxLength() {
int[][] array = new int[][] {
{18,18,19,19,20, 22, 22, 24, 25,26},
{1,2,3},
{0,0,0,0}
};
int i = array.length;
Optional<int[]> longestArray =
Arrays.stream(array)
.max(lengthComparator);
int j = longestArray.isPresent() ? longestArray.get().length : 0;
System.out.println(String.format("i=%d j=%d", i, j));
}
If you happen to create a parallel stream from the array instead, you could speed up this even further.
Another option is to sort the array by length, the quicksort usually has an average complexity of O(n*log(n)) therefore this isn't faster;
int i = array.length;
Arrays.parallelSort(array, lengthComparator);
int j = array[i-1].length;
System.out.println(String.format("i=%d j=%d", i, j));
Your i is the number of rows, which is simply the length of the 2-D array (assuming you are OK with including empty/null rows in this count).
The max row length j, however, would require iterating over all the rows to find the row i having the maximum arr[i].length.
There will always be a loop1, even though the looping will be implicit in solutions that use Java 8 streams.
The complexity of getting the max number of columns is O(N) where N is the number of rows.
Implicit looping using streams probably will be less efficient than explicit looping using for.
Here's a neat solution using a for loop
int max = o;
for (int i = 0; i < array.length; i++) {
max = Math.max(max, array[i].length);
}
This works in the edge-case where array.length == 0, but if array or any array[i] is null you will get a NullPointerException. (You could modify the code to allow for that, but if the nulls are not expected, an NPE is probably a better outcome.)
1 - In theory, you could unroll the loops for all cases of array.length from 0 to Integer.MAX_VALUE, you would not need a loop. However, the code would not compile on any known Java compiler because it would exceed JVM limits on bytecode segments, etcetera. And the performance would be terrible for various reasons.
You could try this way: loop on the array and find the max length of the arrays which is in this array
byte[][] arrs = new byte[3][];
int maxLength = 0;
for (byte[] array : arrs) {
if (maxLength < array.length) {
maxLength = array.length;
}
}
I am creating a code here but I believe there is a way making the following more efficient. I tried many ways but it does not seem to work.
protected void randomise() {
int[] copy = new int[array().length]; //This makes the new int called randomIndex
// used to indicate if elements have been used
boolean[] used = new boolean[array().length]; //calling "used" as a new boolean for the array
Arrays.fill(used,false);
/**
* if index = 0, it means their is nothing in the index.
* if you apply a random number, it will copy that number to an array called index.
* if randomIndex in use, then the boolean becomes true.
*/
for (int index = 0; index < array().length;) {
do {
randomIndex = randomIndex();
} while (used[randomIndex]); //when random is in use, do the follow instruction.
copy[index] = array[index]; //copy the value value to an array called index.
used[randomIndex] = true; //when randomIndex is in use, then it becomes true.
}
//Of course, if there an extra random stores in the array, the index list is increased by one (index++).
for (int index =0;index < array().length; index++) {
array()[index] = copy[index]; //This tells where to copy the index value. in this case, it is a index array.
}
Do you have to use randomIndex?
If not you can use your bool[] to eliminate that do {} while() by sequentially adding the value to copy (which isn't a great name) and choosing a randInt in the range of the len of elements that haven't been selected, then using that bool[] to count a walk through the array elements ( to make your choice for the next element in copy.
You seem to want to randomly re-order an array. If so, then indeed there is a much more efficient solution. You are currently keeping two extra arrays on the size of the input (O(n)) while you do not have to.
The random shuffling is a common problem, and obviously there have been proposed several algorithms to accomplish this task. One of the most efficient algorithms is Knuth's algorithm for random permutation
The algorithms idea is, loop over the array once, and for each number i, perform a random exchange between i and a (random) array index between 0 and i. This guarantees that the array with be shuffled (meaning that each item will have equal possibility to be placed in each of the array indexes), in O(n) time and without using any extra space.
In short,
for (int i = 0; i < index; i++) {
int r = random.nextInt(i + 1);
exchange(array, i, r);
}
It is simple - use some collection of indexes and remove element when you used it. This way should looks like:
List<Integer> indexes = new ArrayList<>(array.length);
for (int i = 0 ; i < array.length ; i++) {
indexes.add(i);
}
Random r = new Random();
while (indexes.size() > 0) {
int randomIndex = r.nextInt(indexes.size());
int index = indexes.remove(randomIndex);
copy[index] = array[index];
}
Please note that:
you should check what is exact collection will be more efficient in your situation
Another way - create list values for array and use Collections.shuffle method on this list.
Additional another way - use some recursive algorithm to do that work.
I was reading this post on Stack overflow: copy a 2d array in java and I am a little confused on how the clone method works here...
public int[][] CopyMap(int[][] Map)
{
int [][] copy = new int[Map.length][];
for(int i = 0; i < Map.length; i++)
copy[i] = Map[i].clone();
return copy;
}
I know how to copy using enhanced for loops but I would like to fully understand this way.
1) Why do we put the Map.length in the first set of square brackets but not Map[0].length in the second set of square brackets for int[][] copy = new int[Map.length][];? Don't we have to initialize the length of the columns as well? I'm guessing that we can't clone a 2D array but we can clone a row or column at a time.
2) By cloning the columns one column at a time and putting it into our 2D array it sets the length of the columns for us?
3) Could we reverse this code by doing this
public int[][] CopyMap(int[][] Map)
{
int [][] copy = new int[][Map[0].length];
for(int i = 0; i < Map[0].length; i++)
copy[i] = Map[i].clone();
return copy;
}
4) Also copy[i] ? This is a 2D array, so shouldn't it be copy[i][] ? Or something like that.
In Java a 2D array is essentially an array of arrays (possibly with different lengths). It is important to remember this. For example, this is OK:
int[][] ar = new int[2][];
ar[0] = new int[8]; // ar[0][0..7]
ar[1] = new int[4]; // ar[1][0..3]
The syntax new int[8][10] can be used as a convenience to create 8 separate arrays of 10 elements each.
If you are familiar with C: an int[][] in Java is more similar to an int** in C.
Note: Map is a terrible name for a variable in Java; variable names generally start with lowercase letters and there is also a very common base container interface of the same name.
1) Why do we put the Map.length in the first set of square brackets but not Map[0].length in the second set of square brackets for int [][] copy = new int[Map.length][]; ?
Because we are starting with an array of Map.length int[]'s, and then cloning those int[]s one at a time.
Don't we have to initialize the length of the columns as well?
No, because when we go through each int[] in Map, we just use clone() to copy it: copy[i] = Map[i].clone().
By cloning the columns one column at a time and putting it into our 2D array it sets the length of the columns for us?
A "column" is just a concept you made up that is only relevant to tabular data (column-major tabular data in your specific context). Anyways, "setting the length" isn't exactly accurate because it implied that something whose length is being set existed in the first place; but when you do int x[][] = new x[5][], x[0] is null until you assign it to something. By cloning the int[]s one at a time, we're just... cloning them one at a time. So, yes, each clone will be the same size as the original.
3) Could we reverse this code by doing this
public int[][] CopyMap(int[][] Map)
{
int [][] copy = new int[][Map[0].length];
for(int i = 0; i < Map[0].length; i++)
copy[i] = Map[i].clone();
return copy;
}
No; and hopefully the reason why is clear now that you know that an int[][] is an array of arrays. The expression new int[][size] doesn't make much sense; it says that we want each int[] in the array to have a given size, but it doesn't say how many int[]s are in the array. It's wrong for the same reason that int[] x = new int[] is wrong.
4) Also copy[i] ? This is a 2D array, so shouldn't it be copy[i][] ? Or something like that.
No, it should be copy[i]. I'll leave figuring out the reasons as an exercise.