我们给出方形二进制矩阵,边 n 我们会将包含至少一个0的任何行或列视为“坏” 任务是使所有不良行和列无效 任务需要使用O(1)额外的内存。
1 1 0 0 0 0
1 1 1 => 1 0 0
1 0 1 0 0 0
很难的是,当我们在遍历期间发现它们时,我们无法使坏线无效(否则我们将始终以归零矩阵结束)。所以我正在寻找这样的数据结构或这种数据表示方式,因此它可以存储关于坏行和列的所有信息,而算法是通过矩阵迭代的。
答案 0 :(得分:3)
实际上我们只需要2n位来得到答案:我们需要知道每一行和列是好(1)还是坏(0)。每个单元格中的答案都是行和列答案的乘积。
让我们将大部分信息存储在矩阵中: 我们可以使用第一行来保留所有列的记录(0或1),但首先, 第一列保留所有行的记录,但首先,我们还需要两个位来保存第一行和第一列的记录。
首先我们得到这两个额外的位(检查第一行和第一列)。
然后查找并存储其他行和列的记录。
然后计算除第一行和列之外的所有矩阵中的结果位。
最后:第一行如果不好则应该无效,并保持不变,并且第一行也应该这样做。
答案 1 :(得分:0)
作为第一步,在网格中查找0。如果我们找不到,我们就完成了。
如果我们找到一个,我们知道我们应该使0的行和列中的所有1都无效。
因此,由于我们知道所有这些单元格的最终值,我们可以将该行和列用作临时布尔标志,以确定相同的行或列是否包含任何0。
确切的过程:
以线性时间(O(mn),m行和n列)和O(1)空间运行。
示例:强>
输入:
1 1 0 1 0
1 1 1 0 1
1 0 1 1 1
1 1 1 1 1
1 1 1 1 1
然后我们寻找零,让我们说我们找到了中上层的。
然后我们使用顶行和中间列作为标志,表示同一行/列是否包含0:
0 1 0 1 1
1
1
0
0
然后我们遍历其他单元格,如果设置了标志行/列,则将1设置为0:
0 0 0 0
0 0 0 0
1 0 0 0
1 0 0 0
然后我们将标志行和列设置为0:
0 0 0 0 0
0
0
0
0
然后我们得到最终结果:
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
1 0 0 0 0
1 0 0 0 0
这显然是就地完成的,我只是为了清晰而将其分开。
答案 2 :(得分:0)
我编写了C ++实现,并给出了Natalya Ginzburg的有用答案。
把它留在这里,以防它对某人有用。
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
class Matrix {
public:
Matrix(int n):
side(n),
stride( round(n/8+1) ),
is0RowGood(true),
is0ColGood(true) {
printf("%d %d\n", side, stride);
data = new char[stride*side];
memset(data, 0, stride*side*sizeof(char) );
if( !data ) {
printf("alloc problem\n");
exit(1);
}
fill();
print();
}
~Matrix() {
if(data)
delete data;
}
void process() {
for( int j = 0; j < side; ++j ) {
if(getEl(0, j) == false) {
is0RowGood = false;
break;
}
}
for( int i = 0; i < side; ++i ) {
if(getEl(i, 0) == false) {
is0ColGood = false;
break;
}
}
for( int i = 1; i < side; ++i ) {
for( int j = 1; j < side; ++j ) {
if(!getEl(i,j)) {
setEl(i,0, false);
break;
}
}
}
for( int j = 1; j < side; ++j ) {
for( int i = 1; i < side; ++i ) {
if(!getEl(j,i)) {
setEl(0, i, false);
break;
}
}
}
// nullify now
for( int i = 1; i < side; ++i ) {
for( int j = 1; j < side; ++j ) {
if( !getEl(0,j) || !getEl(i,0) )
{
crossRow(i);
crossCol(j);
}
}
}
if(!is0RowGood)
crossRow(0);
if(!is0ColGood)
crossCol(0);
printf("--\n");
print();
}
private:
void crossRow(int x) {
for(int i = 0; i < side; ++i ) {
setEl(x, i, false);
}
}
void crossCol(int x) {
for(int i = 0; i < side; ++i ) {
setEl(i, x, false);
}
}
void print() {
for( int i = 0; i < side; ++i ) {
for( int j = 0; j < side; ++j ) {
printf(" %d ", getEl(i,j));
}
printf("\n");
}
}
void fill() {
for( int i = 0; i < side; ++i ) {
for( int j = 0; j < side; ++j ) {
usleep(15);
setEl(i, j, (rand() % 30 == 0) ? 0 : 1);
}
}
}
bool getEl(int i, int j) {
int offset = trunc(i/8) + j*stride;
char byte = data[offset];
return byte & static_cast<char>(pow(2, i%8));
}
bool setEl(int i, int j, bool val) {
int offset = trunc(i/8) + j*stride;
if(val)
data[offset] |= static_cast<char>(pow(2, i%8));
else
data[offset] &= static_cast<char>(255-pow(2, i%8));
}
bool is0RowGood;
bool is0ColGood;
char* data;
int side;
int stride;
};
int
main( int argc,
const char** argv ) {
if(argc < 2) {
printf("give n as arg\n");
exit(1);
}
time_t t;
if(argc == 3)
t = atoi(argv[2]);
else {
t = time(NULL);
printf("t=%d",t);
}
srand (t);
int n = atoi( argv[1] );
printf("n=%d\n",n);
Matrix m(n);
m.process();
}
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
class Matrix {
public:
Matrix(int n):
side(n),
stride( round(n/8+1) ),
is0RowGood(true),
is0ColGood(true) {
printf("%d %d\n", side, stride);
data = new char[stride*side];
memset(data, 0, stride*side*sizeof(char) );
if( !data ) {
printf("alloc problem\n");
exit(1);
}
fill();
print();
}
~Matrix() {
if(data)
delete data;
}
void process() {
for( int j = 0; j < side; ++j ) {
if(getEl(0, j) == false) {
is0RowGood = false;
break;
}
}
for( int i = 0; i < side; ++i ) {
if(getEl(i, 0) == false) {
is0ColGood = false;
break;
}
}
for( int i = 1; i < side; ++i ) {
for( int j = 1; j < side; ++j ) {
if(!getEl(i,j)) {
setEl(i,0, false);
break;
}
}
}
for( int j = 1; j < side; ++j ) {
for( int i = 1; i < side; ++i ) {
if(!getEl(j,i)) {
setEl(0, i, false);
break;
}
}
}
// nullify now
for( int i = 1; i < side; ++i ) {
for( int j = 1; j < side; ++j ) {
if( !getEl(0,j) || !getEl(i,0) )
{
crossRow(i);
crossCol(j);
}
}
}
if(!is0RowGood)
crossRow(0);
if(!is0ColGood)
crossCol(0);
printf("--\n");
print();
}
private:
void crossRow(int x) {
for(int i = 0; i < side; ++i ) {
setEl(x, i, false);
}
}
void crossCol(int x) {
for(int i = 0; i < side; ++i ) {
setEl(i, x, false);
}
}
void print() {
for( int i = 0; i < side; ++i ) {
for( int j = 0; j < side; ++j ) {
printf(" %d ", getEl(i,j));
}
printf("\n");
}
}
void fill() {
for( int i = 0; i < side; ++i ) {
for( int j = 0; j < side; ++j ) {
usleep(15);
setEl(i, j, (rand() % 30 == 0) ? 0 : 1);
}
}
}
bool getEl(int i, int j) {
int offset = trunc(i/8) + j*stride;
char byte = data[offset];
return byte & static_cast<char>(pow(2, i%8));
}
bool setEl(int i, int j, bool val) {
int offset = trunc(i/8) + j*stride;
if(val)
data[offset] |= static_cast<char>(pow(2, i%8));
else
data[offset] &= static_cast<char>(255-pow(2, i%8));
}
bool is0RowGood;
bool is0ColGood;
char* data;
int side;
int stride;
};
int
main( int argc,
const char** argv ) {
if(argc < 2) {
printf("give n as arg\n");
exit(1);
}
time_t t;
if(argc == 3)
t = atoi(argv[2]);
else {
t = time(NULL);
printf("t=%d",t);
}
srand (t);
int n = atoi( argv[1] );
printf("n=%d\n",n);
Matrix m(n);
m.process();
}