Big O notation O(NM) or (N^2) - java

I've been told the below code is = O(MN) however, I come up with O(N^2). Which is the correct answer and why?
My thought process:
nested for loops plus if statements --> (O(N^2)+O(1)) + (O(N^2)+O(1)) = O(N^2)
Thank you
public static void zeroOut(int[][] matrix) {
int[] row = new int[matrix.length];
int[] column = new int[matrix[0].length];
// Store the row and column index with value 0
for (int i = 0; i < matrix.length; i++)
{
for (int j = 0; j < matrix[0].length;j++) {
if (matrix[i][j] == 0)
{
row[i] = 1;
column[j] = 1;
}
}
}
// Set arr[i][j] to 0 if either row i or column j has a 0
for (int i = 0; i < matrix.length; i++)
{
for (int j = 0; j < matrix[0].length; j++)
{
if ((row[i] == 1 || column[j] == 1)){
matrix[i][j] = 0;
}
}
}
}

What does M and N refers to? My assumption is that it refers to "rows" and "columns" respectively. If it is so, then the equation is O(MN) because you loop through M number of N times.
O(N^2) will be correct IF rows and columns are equal.

Related

Print sums of each column & sums of each row of Matrix in Java

I'm stuck on how to find the sums of each column & row of Matrix in Java. I don't know how to find the result of column and row separately. Thank you in advance.
public static void main(String[] args) {
double [][] a = new double [2][3];
a[0][0] = 1;
a[0][1] = 2;
a[0][2] = 3;
a[1][0] = 4;
a[1][1] = 5;
a[1][2] = 6;
for (int i = 0; i < a.length; i++) {
String str = "";
for (int j = 0; j < a[i].length; j++) {
str += a[i][j] + "\t";
}
System.out.println(str);
}
// column sums
double[] b = new double[a[0].length];
// row sums
Use two nested loops:
for(int i = 0; i < b.length; i++) {
b[i] = 0;
for(int j = 0; j < a.length(); j++) {
b[i] += a[j][i];
}
}
You get the sum of a one-dimensional segment of a n-dimensional array, you will need to form a nested loop to iterate through n-dimensional array, with a loop for each dimension. At the deepest step of each iteration, once you are inside the inner-most nested loop, you can increment the total value by the value referenced at that particular point in iteration.
double[][] a = new double[2][3];
a[0][0] = 1;
a[0][1] = 2;
a[0][2] = 3;
a[1][0] = 4;
a[1][1] = 5;
a[1][2] = 6;
for (int row = 0; row < a.length; row++) {
for (int col = 0; col < a[row].length; col++) {
System.out.print(a[row][col] + "\t");
}
System.out.println("");
}
double[] rowTotals = new double[a.length];
double[] colTotals = new double[a[0].length];
for (int row = 0; row < a.length; row++) {
for (int col = 0; col < a[row].length; col++) {
rowTotals[row] += a[row][col];
colTotals[col] += a[row][col];
}
}
I notice in your question you wanted to find the row and column totals separately. If this is a must (I can't see why), you can simply duplicate the nested loop and dedicate one loop for column totals and one for row totals.
//Considering
// row1: 123
// row2: 456
List<Double> colsSum = new ArrayList<>(Collections.nCopies(a[0].length, 0.0));
List<Double> rowsSum = new ArrayList<>();
for(int i = 0; i < a.length; i++){
double row = 0;
for(int j = 0; j < a[i].length; j++){
row += a[i][j];
colsSum.set(j, colsSum.get(j) == 0 ? a[i][j]
: colsSum.get(j) + a[i][j]);
}
rowsSum.add(row);
}

How do I remove placeholding values from a two dimensional array in Java?

I have an int[ ][ ] a that contains both positive and negative integers. I want to copy only the positive integers into another array, int[ ][ ] result.
Here's my attempt:
for( int r = 0; r < a.length; r ++ )
{
int aC = 0;
for( int resC = 0; resC < result[r].length; resC++ )
{
while (a[r][aC] < 0)
{
aC++;
}
result[r][resC] = a[r][aC];
aC++;
}
}
When I run the program it crashes on line 6 quoting a java.lang.ArrayIndexOutOfBoundsException: 3 error. When I run the debugger I can see that it works so long as r = 0.
I feel like I'm missing something blindingly obvious but after staring at it for an hour I still can't find the problem.
Why have 3 loops? Just loop your 2 dimensions and copy positive values:
for (int r = 0; r < a.length; r++)
for (int c = 0; c < a[r].length; c++)
if (a[r][c] > 0)
result[r][c] = a[r][c];
Unless of course you want to condense the values (question didn't say, but code attempt seems to indicate). Or did you also want to truncate?
Input Copy Condensed Truncated
-1 1 2 0 1 2 1 2 0 1 2
-1 -1 3 ==> 0 0 3 ==> 3 0 0 ==> 3
4 -1 5 4 0 5 4 5 0 4 5
Here is a version with truncation:
int[][] result = new int[a.length][];
for (int r = 0; r < a.length; r++) {
int count = 0;
for (int c = 0; c < a[r].length; c++)
if (a[r][c] > 0)
count++;
result[r] = new int[count];
for (int c = 0, cRes = 0; c < a[r].length; c++)
if (a[r][c] > 0)
result[r][cRes++] = a[r][c];
}
When we reach the inner for loop,
we don't have any guarantees about result[r],
and so r may very well be out of bounds.
Instead of this:
for (int r = 0; r < a.length; r++) {
int aC = 0;
for (int resC = 0; resC < result[r].length; resC++) {
The code will be safer like this:
for (int r = 0; r < a.length; r++) {
int aC = 0;
for (int resC = 0; resC < a[r].length; resC++) {
Because, we know that a[r] will be within bounds.
But this is not nearly enough.
The innermost while loop is also likely to try to access an index out of bounds, in fact it's inevitable when you have at least one negative value.
Actually you need to invert the looping logic there,
instead of iterating over indexes in result,
it will make more sense to iterate over indexes in the source.
Like this:
for (int r = 0; r < a.length; r++) {
int resC = 0;
for (int aC = 0; aC < a[r].length; aC++) {
if (a[r][aC] < 0) {
continue;
}
result[r][resC++] = a[r][aC];
}
}
Finally, with variables renamed, it becomes a lot easier to understand what the code is trying to do:
for (int row = 0; row < source.length; row++) {
int targetCol = 0;
for (int col = 0; col < source[row].length; col++) {
if (source[row][col] < 0) {
continue;
}
target[row][targetCol++] = source[row][col];
}
}
You have no bounds checking on
a[r][aC]
so
while (a[r][aC] < 0)
will fail.
Also as you will now have uneven sized arrays, it would be better to to add to an ArrayList, and then convert to an array afterwards if necessary.
Something like
ArrayList <Integer> posValues = new ArrayList <Integer> ();
for( int r = 0; r < a.length; r ++ )
{
for( int c = 0; c < a[r].length; c++ )
{
if (a[r][c] > 0)
{
posValues.add (new Integer (a[r][c]));
}
}
}

Shifting a 2D array to the left loop

I have a 2D array with values in it. Example below:
010101
101010
010101
I want to create a loop that shifts these values to the left like the example below.
101010
010101
101010
So the element that "falls off" goes back in to the end. I'm having a hard time solving this issue in code.
Anyone got any advice?
So far I have made it scroll but I have no clue how to get the elements that fall off to go back in.
This is what I have so far.
for (int row = 0; row < array.length; row++) {
for (int col = 0; col < array[row].length; col++) {
if (!(row >= array.length) && !(col >= array[row].length - 1)) {
array[row][col] = array[row][col + 1];
}
}
}
Try using the modulus operator:
arrayShifted[row][col] = array[row][(col + 1) % array[row].length];
Remove your condition check as well. Also note, to avoid overwriting values, you'll need to store the results in a new array.
for (int row = 0; row < array.length; row++) {
for (int col = 0; col < array[row].length; col++) {
arrayShifted[row][col] = array[row][(col + 1) % array[row].length]
}
}
Here is a full method that takes in a variable amount of spots to shift each row and properly handles copying the same elements as in the modulus approach.
public void shiftArray(int[][] array, int shift) {
for (int row = 0; row < array.length; row++) {
int rowLength = array[row].length;
// keep shift within bounds of the array
shift = shift % rowLength;
// copy out elements that will "fall off"
int[] tmp = new int[shift];
for (int i = 0; i < shift; i++) {
tmp[i] = array[row][i];
}
// shift like normal
for (int col = 0; col < rowLength - shift; col++) {
array[row][col] = array[row][col + shift];
}
// copy back the "fallen off" elements
for (int i = 0; i < shift; i++) {
array[row][i + (rowLength - shift)] = tmp[i];
}
}
}
Test Run
int[][] array = new int[][] {
{0,1,0,1,0,1},
{1,0,1,0,1,0},
{0,1,0,1,0,1}
};
shiftArray(array, 1);
for (int[] row : array) {
for (int col : row) {
System.out.print(col);
}
System.out.println();
}
// 101010
// 010101
// 101010

Printing ragged array column by column

Given an array of integers with rows of different lengths, is it possible to print the whole two-dimensional array but doing so column by column? I understand how to do it row by row but I am struggling with this.
int[][] a = new int[5][];
a[0] = new int[4];
a[1] = new int[2];
a[2] = new int[5];
a[3] = new int[3];
a[4] = new int[1];
int longestRowLength = a[0].length;
for(i = 1; i < a.length; i++)
{
if(a[i].length > longestRowLength)
longestRowLength = a[i].length;
}
for(i = 0; i < a.length; i++)
{
for(j = 0; j < a[i].length; j++)
{
a[i][j] = rand.nextInt(10);
System.out.print(a[i][j]);
}
System.out.println();
}
for(j = 0; j < longestRowLength; j++)
{
for(i = 0; i < a.length; i++)
{
if(a[i].length < longestRowLength)
continue;
System.out.print(a[i][j]);
}
}
}
I have done this but the issue is with how to recognize we are going out of bounds with one of the arrays. My if(a[i].length < longestRowLength doesn't work as it will not even print any numbers if its length is not the longest ones. How can I achieve this?
EDIT:
Ok I have changed that line to:
if(longestRowLength - a[i].length > 0 && (j+1) > a[i].length)
continue;
System.out.print(a[i][j]);
Now it works but it prints the columns as rows. Is there anyway to make it print column by column but to make it print just like it would with rows? (P.S. yeah the first condition of the if statement is unecessary).
Replace your last loop with:
for(j = 0; j < longestRowLength; j++)
{
for(i = 0; i < a.length; i++)
{
if(a[i].length <= j)
continue;
System.out.print(a[i][j]);
}
System.out.println();
}
Prints the columns one by one.
Instead of:
if(a[i].length <= j)
continue;
you can do:
if(a[i].length <= j) {
System.out.print(' ');
continue;
}
to leave a space for arrays which are too short. This way you print the transposed “jagged” matrix.

Add to ListArray from Array

For an array, how can i take all the values at even indexes and add to nameArray and all the values at odd indexes and add to scoreArray? I got this code but it isn't working.
String[] inputArray = {"john", "10", "frank", "14"}
for (int j = 0; j == inputArray.length; j++) {
if ((j % 2) == 0) {
nameArr.add(inputArray[j]);
} else {
scoreArr.add(inputArray[j]);
}
}
You probably mean for (int j = 0; j < inputArray.length; j++)
j == inputArray.length is evaluated to false at the first iteration so your loop doesn't run.
However, you could get rid of the if statement (assuming that your inputArray always contains a name associated a score, i.e always contains pair values) :
for (int j = 0; j < inputArray.length; j+=2) {
nameArr.add(inputArray[j]);
scoreArr.add(inputArray[j+1]);
}
Or you could also use a Map<String, Integer> to associate each name with its corresponding score (assuming names are unique) :
for (int j = 0; j < inputArray.length; j+=2)
m.put(inputArray[j], Integer.parseInt(inputArray[j+1]));
You probably mean to have a < in your loop and not a == and also, try using inputArray and not split2[] like this:
for (int j = 0; j < inputArray.length; j++) {
if ((j % 2) == 0) {
nameArr.add(inputArray[j]);
} else {
scoreArr.add(inputArray[j]);
}
}
What you want to do is look through each element in the array, to do this you want to go through every element starting at 0 and ending at the lengthof the array -1 (because arrays are 0 indexed). Once you are in the loop you want to check if it is an even or odd number using the modulo operator.
for (int j = 0; j < inputArray.length; j++){
if ((j % 2) == 0) {
nameArr.add(inputArray[j];
} else {
scoreArr.add(inputArray[j];
}
}

Categories