Reverse a multidimensional array - java

I am trying to reverse a multidimensional array where the amount of columns in each row are not the same.
Right now, I've managed to reverse the array in the example, but what if column size change in each row? lets say the array consist of {{1},{1,2,3}, {1,2}.......} is there a smarter way to do this without using if-statements for each row?
int[][] array3 = new int[3][4];
int[][] array4 = {{1,2,3},{7,8,6},{3,2,1,0}};
int counter = 2;
for(int row=0; row<array4.length; row++)
{
if(row == 2)
counter = 3;
for(int col=0; col<array4[row].length; col++)
{
array3[row][counter] = array4[row][col];
counter--;
}
counter = 2;
}

You can use two simple for loops iterating over the arrays and creating a new one:
int[][] reversed = new int[array.length][];
for (int i = 0; i < array.length; i++) {
int[] row = array[array.length - i - 1];
reversed[i] = new int[row.length];
for (int j = 0; j < row.length; j++) {
reversed[i][j] = row[row.length - j - 1];
}
}
With Java Streams you can use this, which does the same:
int[][] reversed = IntStream.rangeClosed(1, array.length)
.mapToObj(i -> array[array.length - i])
.map(row -> IntStream.rangeClosed(1, row.length)
.map(i -> row[row.length - i])
.toArray())
.toArray(int[][]::new);
For the input array you showed:
int[][] array = {{1, 2, 3}, {7, 8, 6}, {3, 2, 1, 0}};
The result with both solutions will be this:
[[0, 1, 2, 3], [6, 8, 7], [3, 2, 1]]

Related

Calculating the sum for each array column

I have a 2d-array data, as an example I choose those numbers:
int[][] data = {
{1, 2, 3, 4},
{1, 2, 3, 4},
{1, 2, 3, 4}};
For each column I want to add the sum of numbers together and save them in seperate integers.
This is the result im looking for:
c_zero = 3;
c_one = 6;
c_two = 9;
c_three = 12;
This is the code I have thus far:
int c_zero = 0;
int c_one = 0;
int c_two = 0;
int c_three = 0;
for (int a = 0; a < data.length; a++) {
for (int b = 0; b < data.length; b++) {
for (int[] row : data)
for (int value : row) {
if (int[] row == 0) { //this does not work
c_zero += value;
}
if (int[] row == 1) { //this does not work
c_one += value;
}
...
}
}
}
How can I get the values for each row in a specific row?
I would create a 1D integer array and use that to store the running sum for each column:
int[][] data = {{1,2,3,4},
{1,2,3,4},
{1,2,3,4}};
int[] colSums = new int[data[0].length];
for (int r=0; r < data.length; ++r) {
for (int c=0; c < data[r].length; ++c) {
colSums[c] += data[r][c];
}
}
System.out.println(Arrays.toString(colSums)); // [3, 6, 9, 12]
Using Java 8, you can apply the reduce method to the stream over the rows of a 2d array to sum the elements in the columns and produce a 1d array of sums.
// array must not be rectangular
int[][] data = {
{1, 2, 3, 4},
{1, 2, 3, 4},
{1, 2, 3, 4, 5}};
int[] sum = Arrays.stream(data)
// sequentially summation of
// the elements of two rows
.reduce((row1, row2) -> IntStream
// iterating over the indexes of the largest row
.range(0, Math.max(row1.length, row2.length))
// sum the elements, if any, or 0 otherwise
.map(i -> (i < row1.length ? row1[i] : 0)
+ (i < row2.length ? row2[i] : 0))
// array of sums by column
.toArray())
.orElse(null);
// output of an array of sums
System.out.println(Arrays.toString(sum));
// [3, 6, 9, 12, 5]
// output by columns
IntStream.range(0, sum.length)
.mapToObj(i -> "Column " + i + " sum: " + sum[i])
.forEach(System.out::println);
//Column 0 sum: 3
//Column 1 sum: 6
//Column 2 sum: 9
//Column 3 sum: 12
//Column 4 sum: 5
See also:
• Adding up all the elements of each column in a 2d array
• How to create all permutations of tuples without mixing them?

Filling a jagged 2d array first by columns

I want to write a function that takes an 2d array and fills it with 1...n but counting the columns first instead of the rows:
input = {{0, 0, 0, 0}, {0}, {0}, {0, 0}};
the output should be: {{1, 5, 7, 8}, {2}, {3}, {4, 6}};
if i were to loop through rows and then colums i get:
private static void fill1(int[][] input) {
int count = 1;
for (int i = 0; i < input.length; i++) {
for (int j = 0; j < input[i].length; j++) {
input[i][j] = count;
count++;
}
}
}
How do I loop through colums first?
You can do this by first transposing your input, executing your fill1 code and then transposing the output again.
See this question for how to transpose a 2 dimensional array in Java: java multi-dimensional array transposing
If you were dealing with a regular 2d matrix, where all the rows had the same number of columns, the code would be a simple modification of the code for filling the matrix row-by-row:
private static void fill1(int[][] input) {
int count = 1;
for (int j = 0; j < input[0].length; j++) {
for (int i = 0; i < input.length; i++) {
input[i][j]= count;
count++;
}
}
}
The process is basically the same for a ragged 2d array, but with a couple added twists:
You need to do some extra work to figure out how many columns there could be (i.e., the maximum row length)
You need to be prepared for the case when there's no cell at a given row/column position.
The following modification of the previous code addresses these issues:
private static void fill1(int[][] input) {
int maxCols = input[0].length;
for (int i = 1; i < input.length; ++i) {
if (input[i].length > maxCols) {
maxCols = input[i].length;
}
}
int count = 1;
for (int j = 0; j < maxCols; j++) {
for (int i = 0; i < input.length; i++) {
if (j < input[i].length) {
input[i][j]= count;
count++;
}
}
}
}
To iterate first over the columns of a jagged 2d array to fill it, you have to know the maximum number of columns beforehand, but if you don't know that, you can iterate to the Integer.MAX_VALUE and check at each step if the columns are still present or not:
int[][] arr = {{0, 0, 0, 0}, {0}, {0}, {0, 0}};
int count = 1;
for (int col = 0; col < Integer.MAX_VALUE; col++) {
boolean max = true;
for (int row = 0; row < arr.length; row++) {
if (col < arr[row].length) {
arr[row][col] = count;
count++;
max = false;
}
}
if (max) break;
}
for (int[] row : arr) {
System.out.println(Arrays.toString(row));
}
Output:
[1, 5, 7, 8]
[2]
[3]
[4, 6]
See also: How do you rotate an array 90 degrees without using a storage array?
To populate a 2d array first by columns, you can use two nested streams. In case of a jagged 2d array, when you don't know beforehand the number of the columns in each row, in an outer stream you can traverse while the columns are still present.
/**
* #param arr array that should be populated.
* #return maximum row length, i.e. columns count.
*/
private static long populate(int[][] arr) {
AtomicInteger counter = new AtomicInteger(1);
return IntStream
// traverse through the array columns
.iterate(0, i -> i + 1)
// process the array rows where
// this column is present
.mapToLong(i -> Arrays.stream(arr)
// filter those rows where
// this column is present
.filter(row -> row.length > i)
// assign a value to the element and increase the counter
.peek(row -> row[i] = counter.getAndIncrement())
// count of rows where this column is present
.count())
// while the columns are still present
.takeWhile(i -> i > 0)
// max columns count
.count();
}
public static void main(String[] args) {
int[][] arr = {{0, 0, 0, 0, 0, 0}, {0, 0}, {0}, {0, 0, 0}};
System.out.println("Max columns count: " + populate(arr));
System.out.println(Arrays.deepToString(arr));
}
Output:
Max columns count: 6
[[1, 5, 8, 10, 11, 12], [2, 6], [3], [4, 7, 9]]
See also: How to create a new List from merging 3 ArrayLists in round robin style?

Transposing matrices in Java

I think I am missing something fundamental here about Java, I am not sure why my code below do not work, my steps:
the input is a 2x2 matrix,
copy the original matrix,
loop through rows then column,
assign original matrix's column values to the rows of the transpose matrix.
static void transpose(int[][] matrix) {
int[][] temp = matrix.clone();
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
matrix[i][j] = temp[j][i];
}
}
}
The problem is use the function clone() because that will create a new matrix sharing only row arrays.
Using the same code style, that works:
int[][] temp = new int[2][2];
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
temp[i][j] = matrix[j][i];
}
}
Note that, as temp is an empty matrix, the comparsion will be temp = matrix.
So this works for a simple 2x2 matrix, but if you need other dimensions, instead of
int[][] temp = new int[2][2];
Use
int[][] temp = new int[matrix[0].length][matrix.length];
By the way, update the reference memory of the matrix is not a good practice. I think your method should return temp matrix.
An entire update, a better method could be this one. Is almost the same you have but it can accept diferent lengths.
public static int[][] transpose(int [][] matrix){
int[][] temp = new int[matrix[0].length][matrix.length];
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
temp[j][i] = matrix[i][j];
}
}
return temp;
}
You can use IntStream instead of for loop:
public static void main(String[] args) {
int[][] m1 = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}};
int[][] m2 = transpose(m1);
Arrays.stream(m2).map(Arrays::toString).forEach(System.out::println);
// [1, 4, 7]
// [2, 5, 8]
// [3, 6, 9]
}
static int[][] transpose(int[][] matrix) {
return IntStream.range(0, matrix.length).mapToObj(i ->
IntStream.range(0, matrix[i].length).map(j ->
matrix[j][i]).toArray())
.toArray(int[][]::new);
}

How to organize columns of 2D array based on sum of columns?

I would like to organize a 2D array in descending order of each columns sum. For example:
3 1 1
2 6 5
5 4 2
The sum of column 1 would be 10, column 2 would be 11, column 3 would be 8. Columns 2 and 1 would need to switch to be sorted in descending order. The updated 2D array would be:
1 3 1
6 2 5
4 5 2
I'm aware of Collections.reverseOrder(), but that only works on sorting 1D arrays in descending order.
Here is the code I am using to get the sum of each column:
int tempSum = 0;
for (int i = 0; i < columns; i++) {
for (int j = 0; j < rows; j++) {
tempSum = array[i][j]
}
//reset tempSum
tempSum = 0;
}
I am currently not doing anything with the tempSum of each column. Any guidance would be great.
Try this.
int[][] transpose(int[][] matrix) {
int rows = matrix.length, cols = matrix[0].length;
int[][] transposed = new int[cols][rows];
for (int r = 0; r < rows; ++r)
for (int c = 0; c < cols; ++c)
transposed[c][r] = matrix[r][c];
return transposed;
}
And
int[][] m = {
{3, 1, 1, 9},
{2, 6, 5, 4},
{5, 4, 2, 6}};
m = transpose(m);
Arrays.sort(m, Collections.reverseOrder(Comparator.comparingInt(row -> IntStream.of(row).sum())));
m = transpose(m);
for (int[] row : m)
System.out.println("\t" + Arrays.toString(row));
output
[9, 1, 3, 1]
[4, 6, 2, 5]
[6, 4, 5, 2]
Or if you need more performance
m = transpose(m);
m = Arrays.stream(m)
.map(row -> new Object() {
int sum = IntStream.of(row).sum();
int[] origin = row;
})
.sorted((a, b) -> Integer.compare(b.sum, a.sum))
.map(obj -> obj.origin)
.toArray(int[][]::new);
m = transpose(m);

Print 2D array with a single for loop

How to print a 2d array in java using a single for-loop?
I tried to search answers but only found solutions using multiple loops.
Example array:
[
[1, 2, 3],
[4, 5],
[6, 7, 8],
[9]
]
Example output (the exact format does not matter):
1, 2, 3, 4, 5, 6, 7, 8, 9
With a single for-loop, not a nested loop.
So not something like this:
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[i].length; j++) {
System.out.print(array[i][j] + " ");
}
}
The principle to read a 2D array with a single loop : one [H,W] 2D matrix could be computed as a 1D matrix of HxW length.
On this basis a solution could be:
int[][] arr = {{1, 2, 3}, {4, 5, 8}, {5, 6, 7}};
int hight = arr.length;
int width = arr[0].length;
for (int i = 0; i < width * hight; i++) {
int li = i / hight;
int col = i % hight;
System.out.print(arr[li][col]);
if (col == width - 1) System.out.println();
}
Output:
123
458
567
If you need to know any algorithm for using only one loop you may try to use some like this:
public static void main(String[] args) {
int[][] arr = {{1, 2}, {3, 4}};
int currSubArrayNum = 0;
for (int i = 0; currSubArrayNum < arr.length; i++) {
System.out.println(arr[currSubArrayNum][i]);
if (i == arr[currSubArrayNum].length - 1) {
currSubArrayNum++;
i = -1;
}
}
}
Output will be next:
1
2
3
4
But if you need some simple solution for use in your program just use Arrays.toString:
public static void main(String[] args) {
int[][] arr = {{1, 2}, {3, 4}};
for (int[] anArr : arr) {
System.out.println(Arrays.toString(anArr));
}
}
With output:
[1, 2]
[3, 4]
You can define the for statement without an increment expression and transfer control of it to the inner if statement as follows:
int[][] arr = {{1, 2, 3}, {4, 5}, {6, 7, 8}, {9}};
for (int i = 0, j = 0; i < arr.length; ) {
if (arr[i] != null && j < arr[i].length) {
System.out.print(arr[i][j] + ", ");
j++;
} else {
j = 0;
i++;
}
}
Output:
1, 2, 3, 4, 5, 6, 7, 8, 9,
Create row and col pointer and update when they reach the edge.
Swift code:
func singleLoopArrayTraversal(_ data: [[Int]]) {
//Time complexity: O(n)
if data.count == 0 {
return
}
var row = 0
var col = 0
while row < data.count {
print("data[\(row)][\(col)] : \(data[row][col])")
if col == data[row].count - 1 {
row += 1
col = -1
}
col += 1
}
}
singleLoopArrayTraversal([[1, 2], [3, 4], [5, 6]])

Categories

Resources