Flattening uneven array - Out of bounds exception error - java

I am trying to flatten this array:
int[][] arr = { {1, 2, 3},
{4, 5},
{6},
null,
{},
{7,8}};
I can see that in the first couple of steps it fills out the new array, but then I get the out of bounds exception error. I don't understand where my mistake is.
public static int[] concAr (int[][] arr) {
int countels=0;
for (int r = 0; r < arr.length; r++) {
if (arr[r] == null|| arr[r].length==0)
continue;
for (int c = 0; c < arr[r].length; c++) {
countels++;
}
}
int[] flatAr = new int[countels];
for(int i = 0; i < countels; i ++) {
if(arr[i]!=null) {
for(int j = 0; j < arr[i].length; j ++) {
flatAr[(i * arr.length) + j] = arr[i][j];
}
}
}
return flatAr;
}

The following indexing is wrong, because array lengths are different
flatAr[(i * arr.length) + j] = arr[i][j];
Use this after setting count to zero:
flatAr[count++] = arr[i][j];

countels is the length of the flattened array, in this case, 8. However, in your second outer loop, you index through the original, unflattened array up to countels, even though your unflattened array only has 6 elements. Once you get past those 6, you get the out of bounds exception.
The second time through, you still need to iterate the way you did the first time, and increment the index of the flattened array within the second set of loops.

Related

(Java) Search indexes of values of an array in another array

I have written the following code that takes two arrays and searches the index of the first occurrence of each value from the first array in the second one. For example if first = {15, 10, 18, 17, 15} and second = {10, 15, 10, 17} then the output would be an array with an equal length to first which contains the indices output = {1, 0, -1, 3, 1}, as e.g. 15 occurs in index 1 of the second array, 10 occurs at the 0th index, etc. The index will be -1 if the value in first doesn't occur in second. The code I've written to loop through the arrays is as follows:
public static int[] searchIndexes(int[] first, int[] second) {
int[] indices = new int[first.length];
int index = -1;
for (int i = 0; i < first.length; i ++) {
for (int j = 0; j < second.length; j ++) {
if (first[i] == second[j])
index = j;
}
indices[i] = index;
}
return indices;
}
However, for the given example the output is instead {1, 2, 2, 3, 1}. I think I do understand the issue; since 10 occurs twice in second then the index of the second occurrence is recorded, but I don't know how to get around this. Putting a break; statement after the if clause doesn't seem to fix it.
This would be straightforward by using the ArrayUtils.indexOf() utility method. Moving through the second array, call ArrayUtils.indexOf() for each of its elements in reference to the first array, storing the results in the indices array. This will also mean that there would be a single loop, not a nested loop.
The ArrayUtils class is a part of the org.apache.commons.lang3 library.
A different option, not requiring an external library, would be to convert your arrays to Lists and then take advantage of the List.indexOf() method.
I hope that helps!
Two issues in your code:
Once index is set to any value at all, it can never again become -1
Once you find the first occurrence in the second array, you keep going - need a break.
Updated code:
public static int[] searchIndexes(int[] first, int[] second) {
int[] indices = new int[first.length];
int index;
for (int i = 0; i < first.length; i ++) {
// reset index on each iteration
index = -1;
for (int j = 0; j < second.length; j ++) {
if (first[i] == second[j]) {
// once the first match is found, break out of the inner loop
index = j;
break;
}
}
indices[i] = index;
}
return indices;
}
try this
public static int[] searchIndexes(int[] first, int[] second) {
int[] indices = new int[first.length];
//fill all values with -1
Arrays.fill(indices,0,first.length - 1, -1);
for (int i = 0; i < first.length; i++) {
for (int j = 0; j < second.length; j++) {
// when you met with same value fill your indices array with second array's value's index and break the loop
if (first[i] == second[j]) {
indices[i] = j;
break;
}
}
}
return indices;
}
Just add break after found the element and reset the index
public static int[] searchIndexes(int[] first, int[] second) {
int[] indices = new int[first.length];
int index = -1;
for (int i = 0; i < first.length; i++) {
index = -1;
for (int j = 0; j < second.length; j++) {
if (first[i] == second[j]) {
index = j;
break;
}
}
indices[i] = index;
}
return indices;
}
, main
public static void main(String args[]) {
int[] indices = searchIndexes(new int[] { 15, 10, 18, 17, 15 }, new int[] { 10, 15, 10, 17 });
for (int i = 0; i < indices.length; i++)
System.out.print(indices[i] + " ");
System.out.println();
}
, output
1 0 -1 3 1

Finding all Indices of a number from an Array (Java)

Say I have an array of:
int [] I = { 1, 3, 6, 3, 7,3, 9, 3};
int value = 3;
I have a for loop that tracks the amount of occurences of the value:
int counter = 0;
for(int x = 0; x < I.length; x++)
{
if(I[x] == value)
{
counter++;
}
}
I make a new array with length equal to the number of occurrences, that can store all the indices of the occurences from the original array:
int [] index = new int [counter];
for(int x = 0; x < index.length; x++)
{
for(int i = 0; i<I.length; i++)
{
if(I[i] == value){
index[x] = i;
}
}
}
However, when I print my array of indices, i just get the last index printed the amount of times counter is equal to, when I want all the indices.
for(int i = 0; i<index.length; i++)
{
System.out.println(index[i]);
}
It just prints "7" (the last index) 3 times. How do I go about fixing this so I have an array of all indices?
Thank you.
Your second for loop should not be nested; you should only increment x when you find a match. Something like,
for (int i = 0, x = 0; i < I.length; i++) {
if (I[i] == value) {
index[x] = i;
x++;
}
}
Assuming you're using Java 8+, you could have written a filter() on the range of indices in the array. Like,
int[] index = IntStream.range(0, I.length).filter(i -> I[i] == value).toArray();
System.out.println(Arrays.toString(index));
Just remove the outer for loop and store into the index array as you iterate through the original array I. The problem with your code is that, since you repeat the iterations once for each index in the index array, you end up with the last found index (7 in your case).
for(int i = 0, x = 0; i < I.length; i++) {
if(I[i] == value) {
index[x++] = i;
}
}

Sorting array contains some arrays in java

I have a array that contains arrays in it.
and I need to write a function that sort the little array on the big array( I mean the minimum sum of the little array is be the first on the index 0 and after the second on index1 and the maximum sum of the little array in in the end of the big aray =index bigArray.length-1
How can I sort an array that contains arrays in it?
i need to do that with no object or things like that. just regular and simple code.
enter image description here
public static int [][] sum (int [][] arr) {
int sum=0;
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr.length; j++) {
sum=sum+arr[i][j];
}
Since summing the inner array is a relatively time-consuming process, and the sum value is needed more than once when sorting, you should create an object to hold the array and the sum, e.g.
static class ArraySum implements Comparable<ArraySum> {
final int[] array;
final int sum;
ArraySum(int[] array) {
this.array = array;
this.sum = Arrays.stream(array).sum();
}
#Override
public int compareTo(ArraySum that) {
return Integer.compare(this.sum, that.sum);
}
}
Since it's Comparable, you can sort it directly, so with that in hand, you can easily sort the outer array using Java 8+ streams:
public static int[][] sort(int[][] arr) {
return Arrays.stream(arr).map(ArraySum::new).sorted()
.map(a -> a.array).toArray(int[][]::new);
}
That doesn't sort the input 2D array, but returns a new 2D array, i.e. a new outer array with the original inner arrays sorted.
Test
int[][] arr = { { 3, 5, 4 }, { 4, 3, 1, 2 }, { 5, 6 } };
int[][] arr2 = sort(arr);
System.out.println(Arrays.deepToString(arr));
System.out.println(Arrays.deepToString(arr2));
Output
[[3, 5, 4], [4, 3, 1, 2], [5, 6]]
[[4, 3, 1, 2], [5, 6], [3, 5, 4]]
// 10 11 12 sum
As you can see, the original 2D array is unmodified, and the new array is sorted by the sum of the inner arrays.
I don't think this works perfectly, but it should definitely get you close. I believe this is a buble sort technique.
public static int [][] sum (int [][] arr) {
//start at first array
for (int i = 0; i < arr.length - 1; i++) {
//sum of first array
int sum1 = 0;
for (int j = 0; j < arr[i].length; j++){
sum1 += arr[i][j];
}
//compare to each of the arrays after
for (int k = i+1; k < arr.length; k++) {
int sum2 = 0;
for (int l = 0; l < arr[k].length; j++){
sum2 += arr[k][l];
}
//if second array is smaller, swap
if (sum2 < sum1){
//might need to change this part to do complete copy
temp = arr[i];
arr[i] = arr[k];
arr[k] = temp;
}
}
}
return arr
}

Flatten a Jagged 2D Array

I have an assignment that asks me to flatten a 2D array into a single array.
Here's what I have so far:
public static int[] flatenArray(int [][] a){
//TODO
int length = 0;
for(int y = 0; y < a.length; y++){
length += a[y].length;
}
int[] neu = new int[length];
int x = 0;
for (int i = 0; i < a.length; i++){
for(int j = 0; j < a[0].length; j++){
neu[x] = a[i][j];
x++;
}
}
return neu;
}
When doing a JUnit Test for the following test case
assertArrayEquals(new int[] {1,2,3,4,5,6,7,8,9,10,11},Ass06.flatenArray(new int[][] {{1,2,3},{4,5,6},{7,8,9,10,11}}));
I get the following error:
arrays differed at element[9]; expected <10> but was <0>
Somehow at the point where the array length of the 3rd "inner array" surpasses 3, the last 2 numbers ("10, 11") are not copied into the new array.
There are multiple ways to solve this this, but it all comes down to you counting things wrong.
In a new int[1], the first element is index 0. In an array of 1 element, .length will return 1, but there will be no array[1]. That's why you're missing the the count by 1.

return an Array which contains only odd integers

Ok, so I have this problem where when given an Array arr, return an Array which contains only odd integers in the original order from arr.
My code:
public int [] youMakeMeOdd(int [] arr)
{
int[] odds;
odds = new int[arr.length];
for(int i = 0; i < arr.length; i++)
{
if(arr[i] % 2 != 0)
{
odds[i] = arr[i];
}
}
return odds;
}
Few Testers:
Expected...........................................................Run:
youMakeMeOdd({1,2,3}) → {1, 3}.....................{1, 0, 3}
youMakeMeOdd({2,1,3,5,7}) → {1, 3, 5, 7}.......{0, 1, 3, 5, 7}
youMakeMeOdd({2,4,6,8}) → {}........................{0, 0, 0, 0}
.
I can't seem to figure out how to put a blank space there instead of 0's. Help appreciated, thanks :)
The output array is being initialized to the size of the input array. I guess this being java code, the array elements are initialized to zero by default. So whenever the if condition does skips the ith position the default value (zero) is being shown.
public int[] youMakeMeOdd(int [] arr) {
List<Integer> odds = new ArrayList<Integer>();
for(int i = 0; i < arr.length; i++)
{
if(arr[i] % 2 != 0)
{
odds.add(arr[i]);
}
}
return convertIntegers(odds);
}
public static int[] convertIntegers(List<Integer> integers)
{
int[] ret = new int[integers.size()];
Iterator<Integer> iterator = integers.iterator();
for (int i = 0; i < ret.length; i++)
{
ret[i] = iterator.next().intValue();
}
return ret;
}
You could have a pre-computation loop where you just increment a counter and then allocate odds:
int counter = 0;
for (int i = 0; i < arr.length; i++)
{
if (arr[i] % 2 != 0)
{
counter ++;
}
}
odds = new int[counter];
I would use an ArrayList. Your problems seems to be the fact that arrays are immutable, so you it automatically fills your array with a bunch of unneeded 0s. ArrayLists can change dimensions, so you don't have to have the 0s.
You can have a look at them here: http://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html
Make sure you import the util package.
import java.util.*;
public ArrayList<Integer> youMakeMeOdd(int [] arr)
{
You need to specify the type that you want to hold in the angle braces. Because int is a primitive, you need to use the Integer class
ArrayList<Integer> odds;
odds = new ArrayList<>();
for(int i = 0; i < arr.length; i++)
{
if(arr[i] % 2 != 0)
{
The add method adds an integer to the end
odds.add(new Integer(arr[i]));
}
}
return odds;
}
var result = input.Select(a=>a % 2 != 0 ? a : 0).ToArray()
You can use linq easily, basically you use the original array and then use the Select to select either the value itself of the array or 0 if it's even, and then convert to an array using ToArray method.

Categories