I have a matrix which looks like this:
| 1 | 0 | 0 | 1 | 0 |
| 1 | 1 | 0 | 1 | 0 |
| 1 | 0 | 1 | 1 | 0 |
| 1 | 0 | 0 | 1 | 0 |
| 0 | 0 | 0 | 1 | 1 |
<
If you don't assume arbitrary content (as in Oli's answer) and you can encode each row as an unsigned integer with binary flags, then you can do it in O(n) and O(1) by just repeatedely performing a logical AND
of each row with the latest result.
The final set of flags will only have ones where the relevant column was also one.
Assuming arbitrary content, you cannot avoid a worst-case of O(n2).* You have to visit every element in each column that you want to consider, and in the worst-case, you have to consider all columns.
n
is the matrix dimension here, not the total number of elements.
My solution is that we first assume that all columns have 1s, then we go row by row, over the possible solutions we still have, and cut columns that cannot be a solution.
This solution is written in Java:
Solution 1: O(n^2) straight-forward
public class Main
{
// Given A: an M x N matrix
public static ArrayList<Integer> solve (Integer [][] matrix)
{
// Assuming all columns have 1s, we have list S
ArrayList<Integer> S = new ArrayList<Integer>();
// S = { 1, 2, .., N }
for (int i=0; i < matrix[0].length; i++)
{
S.add(i);
}
// For Row i: 1..M
for (Integer i = 0; i < matrix.length; i++)
{
// For Column j in list S
for (Integer j : S)
{
if (matrix[i][j] != 1)
{
S.remove(j);
}
}
}
return S;
}
public static void main (String [] args)
{
int [][] matrix =
{
{1,1,1},
{0,1,1},
{0,0,1},
};
ArrayList<Integer> columns = solve (matrix);
System.out.print(" columns that have 1s are: ");
for (Integer n : columns) System.out.print(n+" ");
}
}
Solution 2: O(n) using a customized data-structure
private class Column
{
public ArrayList<Integer> data;
public int count;
public Column ()
{
data = new ArrayList<Integer>();
count = 0;
}
public void add (int val)
{
data.add(val);
count += val;
}
}
public class Main
{
public static void main (String [] args)
{
Column [] matrix =
{
new Column (),
new Column (),
new Column ()
};
matrix[0].add(1);
matrix[0].add(0);
matrix[0].add(0);
matrix[1].add(1);
matrix[1].add(1);
matrix[1].add(0);
matrix[2].add(1);
matrix[2].add(1);
matrix[2].add(1);
System.out.print(" columns that have 1s are: ");
for (Column column : matrix)
{
if (column.count == column.data.size())
System.out.print(n+" ");
}
}
}
Let me take a very wild guess on what you are trying to do. Hint from the mention of:
O(n)
algorithmWell, you can not do that in O(n)
and I can prove that it is O(n^2)
only.
But my wild guess is that you doing a classic celebrity identification problem, and that you misunderstood the problem.
A celebrity is person that is known by every other person, but doesn't know any [other people].
I celebrity identification problem, you are trying to find something like:
Find the number i where
a[i][x] = 1 for all x -> every one knows the celebrity
a[x][i] = 0 for all x != i -> the celebrity doesn't know anyone else
And indeed with this extra constrain on what you are trying to find, there is an O(n)
solution.
What is the input for the matrix?
If you get a number for each column, i.e. in your example (in decimal) 14, 8, 4, 31, 1, you could just create a number a
with n
binary digits set to 1 (in this case 31). If this number is equal to one of the column numbers, one of the columns is all 1s.