Учитывая матрицу размера n x m, заполненную 0 и 1
например:.
1 1 0 1 0
0 0 0 0 0
0 1 0 0 0
1 0 1 1 0
если матрица имеет 1 at (i, j), заполните столбец j и строку я 1
i.e., получим:
1 1 1 1 1
1 1 1 1 0
1 1 1 1 1
1 1 1 1 1
Требуемая сложность: O (n * m) время и O (1) пространство
ПРИМЕЧАНИЕ: вам не разрешено хранить что-либо, кроме "0" или "1" в записях матрицы
Выше интервью Microsoft.
Я думал уже два часа. У меня есть некоторые подсказки, но я не могу больше продолжить.
Ok. Первая важная часть этого вопроса заключается в том, что Even using a straight forward brute-force way
он не может быть легко решен.
Если я просто использую два цикла для итерации по каждой ячейке в матрице и изменяю соответствующую строку и столбец, это невозможно сделать, поскольку результирующая матрица должна быть основана на исходной матрице.
Например, если я вижу a[0][0] == 1
, я не могу изменить row 0
и column 0
все на 1
, потому что это повлияет на row 1
, поскольку row 1
не имеет 0 изначально.
Во-вторых, я заметил, что если строка r
содержит только 0
, а столбец c
содержит только 0
, то a[r][c]
должен быть 0
; для любой другой позиции, которая не находится в этом шаблоне, должна быть 1
.
Затем возникает другой вопрос, если я найду такую строку и столбец, как я могу пометить соответствующую ячейку a[r][c]
как special
, поскольку она уже равна 0.
Я интуитивно понимаю, что я должен использовать для этого какие-то бит-операции. Или, чтобы удовлетворить требуемую сложность, я должен сделать что-то вроде After I take care of a[i][j], I should then proceed to deal with a[i+1][j+1], instead of scan row by row or column by column
.
Даже для грубой силы, не учитывая сложность времени, я не могу решить ее с другими условиями.
У кого-нибудь есть ключ?
Решение: версия Java
@japreiss ответил на этот вопрос, и его/ее ответ разумный и правильный. Его код находится в Python, и теперь я даю версию Java. Кредиты все идут на @japreiss
public class MatrixTransformer {
private int[][] a;
private int m;
private int n;
public MatrixTransformer(int[][] _a, int _m, int _n) {
a = _a;
m = _m;
n = _n;
}
private int scanRow(int i) {
int allZero = 0;
for(int k = 0;k < n;k++)
if (a[i][k] == 1) {
allZero = 1;
break;
}
return allZero;
}
private int scanColumn(int j) {
int allZero = 0;
for(int k = 0;k < m;k++)
if (a[k][j] == 1) {
allZero = 1;
break;
}
return allZero;
}
private void setRowToAllOnes(int i) {
for(int k = 0; k < n;k++)
a[i][k] = 1;
}
private void setColToAllOnes(int j) {
for(int k = 0; k < m;k++)
a[k][j] = 1;
}
// # we're going to use the first row and column
// # of the matrix to store row and column scan values,
// # but we need aux storage to deal with the overlap
// firstRow = scanRow(0)
// firstCol = scanCol(0)
//
// # scan each column and store result in 1st row - O(mn) work
public void transform() {
int firstRow = scanRow(0);
int firstCol = scanColumn(0);
for(int k = 0;k < n;k++) {
a[0][k] = scanColumn(k);
}
// now row 0 tells us whether each column is all zeroes or not
// it also the correct output unless row 0 contained a 1 originally
for(int k = 0;k < m;k++) {
a[k][0] = scanRow(k);
}
a[0][0] = firstCol | firstRow;
for (int i = 1;i < m;i++)
for(int j = 1;j < n;j++)
a[i][j] = a[0][j] | a[i][0];
if (firstRow == 1) {
setRowToAllOnes(0);
}
if (firstCol == 1)
setColToAllOnes(0);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
for (int i = 0; i< m;i++) {
for(int j = 0;j < n;j++) {
sb.append(a[i][j] + ", ");
}
sb.append("\n");
}
return sb.toString();
}
/**
* @param args
*/
public static void main(String[] args) {
int[][] a = {{1, 1, 0, 1, 0}, {0, 0, 0, 0, 0},{0, 1, 0, 0, 0},{1, 0, 1, 1, 0}};
MatrixTransformer mt = new MatrixTransformer(a, 4, 5);
mt.transform();
System.out.println(mt);
}
}