How to improve performance while calculating matrix sum - java

I was given a task during an interview, where I was given a matrix, now I need to generate another matrix out of it using below formula:
Given matrix A[R][C], generate B[R][C]
val = 0;
for (i = 0; i ≤ xPosition; i += 1) {
for (j = 0; j ≤ yPosition; j += 1) {
val = val + a(i, j);
}
}
B(xPosition,yPosition) = val;
I have come up with below code:
public List<List<Integer>> generate(List<List<Integer>> A) {
List<List<Integer>> top = new ArrayList<>();
for (int i = 0; i < A.size(); i++) {
List<Integer> inner = new ArrayList<>();
for (int j = 0; j < A.get(0).size(); j++) {
inner.add(generateValue(A, i, j));
}
top.add(inner);
}
return top;
}
int generateValue(List<List<Integer>> A, int xPosition, int yPosition) {
int val = 0;
for (int i = 0; i <= xPosition; i++) {
for (int j = 0; j <= yPosition; j++) {
int value = A.get(i).get(j);
val += value;
}
}
return val;
}
Sample input :
1 2 3
4 5 6
Output :
1 3 6
5 12 21
How to improve the performance of this logic?

mathematicaly for your solution in array b,each element is related to it's previous one.
to improve your code / optimise it you need to see this relation.
so for every B[i][j] is related to it's previous element and value from the array A.
below is solution mathematically,
b[i][j] = b[i-1][j] + a[i][0]+a[i][1] + a[i][2]+...+a[i][y-1]
for so if you able to implement this, your code will pass all test cases
i am not a java dev, but if you want code, i can write it for you in python

The key is to think of this as a dynamic programming problem, assuming that we have already calculated B[x][y] for all 0 <= x < i, 0 <= y < j when we go to calculate B[i][j].
B[i][j] contains the sum of all elements in the submatrix of A that starts at 0, 0 and ends at i, j. Thus B[i-1][j] will contain the sum of the all the elements in this submatrix except the ones in the ith row. Similarly, B[i][j-1] will contain the sum of the all the elements in this submatrix except the ones in the jth column. Adding these two together, we get the sum of all the elements in the submatrix except for element A[i][j]. However, while doing this we count all the elements from 0, 0 to i-1, j-1 twice, and we have to subtract their sum (which is B[i-1][j-1]) once so that we only sum them up once in total. Then we add the missing element, A[i][j]. Hence
B[i][j] = B[i-1][j] + B[i][j-1] - B[i-1][j-1] + A[i][j]
This recursion can now be implemented as a O(RC) dynamic programming algorithm.
To help understand this further, consider the following figure representing the submatrix for which we have to find the sum of the elements. The figure is a matrix C[i][j], where the x, yth element is the number of times we have summed A[x][y]. In terms of C[i][j], our end goal (B[i][j]) is
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
B[i-1][j] corresponds to the matrix C[i-1][j], which is
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
0 0 0 0 0
B[i][j-1] corresponds to the matrix C[i][j-1], which is
1 1 1 1 0
1 1 1 1 0
1 1 1 1 0
1 1 1 1 0
B[i-1][j] + B[i][j-1] corresponds to the matrix C[i-1][j] + C[i][j-1], which is
2 2 2 2 1
2 2 2 2 1
2 2 2 2 1
1 1 1 1 0
B[i-1][j] + B[i][j-1] - B[i-1][j-1] corresponds to the matrix C[i-1][j] + C[i][j-1] - C[i-1][j-1], which is
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 0
Now B[i-1][j] + B[i][j-1] - B[i-1][j-1] + A[i][j] corresponds to
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
which is the same as B[i][j].

Related

Nested for loop Java confusion

Hi i have a beginner question about nested for-loop in java.
int sum = 0;
for(int i = 1; i < 3; i++){
for(int j = i; j>= 0; j--){
sum += j;
}
}
so here is my trace table
i j sum
1 1 1
0 1
2 2 2
1 3
0 3
My question is why is the output at the end of the loop is 4? is it because 3+1?
Your trace table is wrong. This is the correct one:
i j sum
1 1 1
0 1
2 2 3
1 4
0 4
You sum all values of j (second column), which essentially is 1 + 0 + 2 + 1 + 0 = 4.
Actually we need to make a correction for your table result:
i j sum
1 1 1
0 1
2 2 2 (sum is 2+1(existing sum, sum is not 0 anymore) )
1 3 (sum is 3 + 1 = 4)
0 3 (sum is 4+ 0 = 4)
The output is 4 because sum is:
0 +
1 +
2 + 1 =
= 4
First you add 1, then 2 and 1. Your loops sums all triangle numbers below 3. Triangle numbers are sums of numbers from 1 to n. These are 1, 3, 6, 10 etc..

How can I add up the elements of a row in a 2 dimensional array Java

Hey I'm trying to code a model for the Least Recently Used paging algorithm. I'm relatively new to Java and coding in general and I just can't find the error in my code.
I want to implement the free memory with a 2 dimensional array, and when referencing a row i change the bits in the corresponding row to 1 and in the corresponding column to 0. Then I want to add up the elements in each row and sort them using the bubblesort algorithm.
There lies my Problem: it seems I just can't get the adding up or the sorting right. I hope someone can help me because it seems no matter what I try, it doesn't work.
Here is the part of my code in question since it seems to be in stackoverflows rules that I can't post the whole code.
page [][] is the 2d array which i use to change the bytes.
I would be very grateful for any help because I'm getting demotivated slowly but surely.
// array for bubblesort and adding up of rows
int sort[] = new int[page.length];
int sumtemp = 0;
int sum = 0;
for (int i = 0; i < page.length; i++) {
for (int j = 0; j < page[i].length; j++) {
sumtemp += page[i][j];
sum = sumtemp;
}
for (i = 0; i < page.length; i++)
sort[i] = sum;
sumtemp = 0;
}
// bubblesort
int n1 = sort.length;
int temp = 0;
for (int i = 0; i < n1; i++) {
for (int j = 1; j < (n1 - i); j++) {
if (sort[j - 1] > sort[j]) {
// sort
temp = sort[j - 1];
sort[j - 1] = sort[j];
sort[j] = temp;
}
}
}
My Output: it works until the last output, where the page to be deleted should be 5 not 4:
How many pages shall fit in the memory?
5
Which page do you want to reference? Please choose a number between 1 and 5. Have you finished referencing, please type in
4
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
1 1 1 0 1
0 0 0 0 0
Page to delete = 1
Which page do you want to reference? Please choose a number between 1 and 5.
Have you finished referencing, please type in
3
0 0 0 0 0
0 0 0 0 0
1 1 0 1 1
1 1 0 0 1
0 0 0 0 0
Page to delete = 1
Which page do you want to reference? Please choose a number between 1 and 5.
Have you finished referencing, please type in
1
0 1 1 1 1
0 0 0 0 0
0 1 0 1 1
0 1 0 0 1
0 0 0 0 0
Page to delete = 5
Which page do you want to reference? Please choose a number between 1 and 5.
Have you finished referencing, please type in
2
0 0 1 1 1
1 0 1 1 1
0 0 0 1 1
0 0 0 0 1
0 0 0 0 0
Page to delete = 4
Which page do you want to reference? Please choose a number between 1 and 5. Have you finished referencing, please type in
This should be the Bubble Sort logic:
for (int i = 0; i < n1; i++) {
for (int j = 0; j < (n1 - i - 1); j++) {
if (sort[j + 1] > sort[j]) { //ascending order
// sort
temp = sort[j + 1];
sort[j + 1] = sort[j];
sort[j] = temp;
}
}

the difference between 2d array

I'm wondering what is the difference between these loops in 2D arrays:
for (int r = row - 1, c = column - 1; r >= 0 && c >= 0; r--, c--) {
...
}
for(int r=row-1;r>=0;r--){
for(int c=column-1;c>=0;c--){
...
}
}
for (int r = row - 1, c = column - 1; r >= 0 && c >= 0; r--, c--)
The first example is one loop that decrements both r and c every cycle, meaning that the indices r and c will draw a diagonal starting at array[row-1][column-1].
for(int r=row-1;r>=0;r--){
for(int c=column-1;c>=0;c--){
The second example calls a loop for columns for each index of row, so it will access all the indices array[r][c]
I assume you are asking for the difference between a single outer loop and a nested loop. The difference is that the single loop will iterate over the diagonal of the 2D array and the nested loops with iterate over every index of the array. For instance, if there are 6 rows and 4 columns then:
for (int r = row - 1, c = column - 1; r >= 0 && c >= 0; r--, c--) {
System.out.println(r + " " + c);
}
will yield:
5 3
4 2
3 1
2 0
Whereas the nested loop
for(int r=row-1; r>=0; r--) {
for(int c=column-1; c>=0; c--) {
System.out.println(r + " " + c);
}
}
would yield
5 3
5 2
5 1
5 0
4 3
4 2
4 1
4 0
3 3
3 2
3 1
3 0
2 3
2 2
2 1
2 0
1 3
1 2
1 1
1 0
0 3
0 2
0 1
0 0
The first iterates for n times, where n is the least of row and column. The second iterates for m times, where m is row * column. That is
Math.min(row, column)
and
row * column
respectively.

How do I generate all possible combinations of a 3 x 2 matrix?

I'm stuck trying to create a 3 x 2 matrix that only contains 0 and 1 and prints out all the possible combinations, BUT it can only contain one 1 and one 0 for each row, the numbers have nothing to do with each other than that they are unique, much like a betting table for say tennis or something:
0 1 1 0 0 1 0 1 0 1
0 1 1 0 0 1 1 0 1 0
0 1 1 0 1 0 1 0 0 1
Here's the code:
public class Program {
public static void main(String[] args) {
int[][] array = {{0,1}};
System.out.println("Array:");
for(int row = 0; row < array.length; row++){
for(int column = 0; column < array[row].length; column++){
System.out.print(array[row][column] + " ");
}
System.out.println();
}
}
}
This is what I got right know. I don't know where to take it from here.
For a general case of an N-by-2 matrix there will be 2^N combinations that meet your criteria. Consider that each row can only be in two states: [0, 1], or [1, 0].
Start with a matrix where every row is in the initial state [0, 1]. Then, for every number X where 0 <= X < 2^N, convert X to binary. When the Mth bit is 1, reverse the Mth row's values.
For example, binary 000 would correspond to:
0 1
0 1
0 1
While binary 101 would correspond to:
1 0 (swapped)
0 1
1 0 (swapped)

Pyramid Pattern in Java

It was so hard to ask such a newbie question on this advanced site. But after so much tries and even loosing my hope i was forced to bring my self here. I am not been able to print the following pattern:
1
1 2 1
1 2 4 2 1
1 2 4 8 4 2 1
1 2 4 8 16 8 4 2 1
1 2 4 8 16 32 16 8 4 2 1
But with my tiresome efforts i reached the following:
public static void main(String[] args) {
int num = 1;
for (int i = 0; i < 15; i++) {
for (int j = 0; j < 15 - i; j++) {
System.out.print(" ");
}
for (int k = 0; k <= i; k++) {
System.out.print(num + " ");
}
System.out.println();
}
}
1
1 1
1 1 1
1 1 1 1
1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1
Here ya go
public static void main(String[] args) {
int max = 6;
int padLength = (int) Math.ceil(Math.log10(Math.pow(2, max) + 1)) + 2;
for (int i = 0; i < max; i++) {
for (int j = 1; j < max - i; j++) {
System.out.print(pad(" ", padLength));
}
for (int k = 0; k <= i; k++) {
System.out.print(pad(Math.pow(2, k), padLength));
}
for (int k = i - 1; k >= 0; k--) {
System.out.print(pad(Math.pow(2, k), padLength));
}
System.out.println();
}
}
public static String pad(double d, int l) {
Integer i = (int) d;
return pad(i.toString(), l);
}
public static String pad(String s, int l) {
return String.format("%-" + l + "s", s);
}
Explanation
int padLength = (int) Math.ceil(Math.log10(Math.pow(2, max) + 1)) + 2;
Math.pow(2,max) - Gives me maximal number I will have to display
Math.ceil(Math.log10(number + 1)) - I use this to determine length of string representation of specific number. Please refer to wikipedia to check what logarithm is. I add 1 to skip edge case when number is exact power of 10 e.g. log10(10)->1 (this will never occur in task specified in question, it's just for purity of solution). Ceil just rounds number up.
+2 - minimum gap between two numbers is specified example was 2 spaces long so I just add this
You could use here Integer.toString(((int)Math.pow(2, max))).length()+2 but it's not as pretty :)
return String.format("%-" + l + "s", s);
First I build format string that looks like e.g. %-3s, which means print String with minimum length of 3, padding on the right. Second argument is the String I want to print. Refer to documentation
Running example
I find the other answer very overwhelming and dramatic. You don't need much maths and complexity to solve this problem. This might not be the best code but I think it is easy to understand. Not even an explanation is needed, it is a row by row approach, It's good to keep things simple.
public static void main(String[] args) {
// Init
int row = 0;
int maxRows = 6;
int num = 1;
int indent = maxRows - 1;
// Printing loop
while (row < maxRows) {
// Indent
for (int i = 0; i < indent; ++i)
System.out.print(" ");
// Print nums
for (int i = 0; i < num; ++i)
System.out.printf("%4d", (int) Math.pow(2.0, i));
for (int i = num - 2; i >= 0; --i)
System.out.printf("%4d", (int) Math.pow(2.0, i));
// New line
System.out.println("");
// Adjustments
++row;
--indent;
++num;
}
Output:
1
1 2 1
1 2 4 2 1
1 2 4 8 4 2 1
1 2 4 8 16 8 4 2 1
1 2 4 8 16 32 16 8 4 2 1

Categories