从二进制矩阵中删除坏行

时间:2014-03-06 17:25:36

标签: algorithm matrix

我们给出方形二进制矩阵,边 n 我们会将包含至少一个0的任何行或列视为“坏” 任务是使所有不良行和列无效 任务需要使用O(1)额外的内存。

1 1 0     0 0 0
1 1 1  => 1 0 0
1 0 1     0 0 0

很难的是,当我们在遍历期间发现它们时,我们无法使坏线无效(否则我们将始终以归零矩阵结束)。所以我正在寻找这样的数据结构或这种数据表示方式,因此它可以存储关于坏行和列的所有信息,而算法是通过矩阵迭代的。

3 个答案:

答案 0 :(得分:3)

实际上我们只需要2n位来得到答案:我们需要知道每一行和列是好(1)还是坏(0)。每个单元格中的答案都是行和列答案的乘积。

让我们将大部分信息存储在矩阵中: 我们可以使用第一行来保留所有列的记录(0或1),但首先, 第一列保留所有行的记录,但首先,我们还需要两个位来保存第一行和第一列的记录。

首先我们得到这两个额外的位(检查第一行和第一列)。

然后查找并存储其他行和列的记录。

然后计算除第一行和列之外的所有矩阵中的结果位。

最后:第一行如果不好则应该无效,并保持不变,并且第一行也应该这样做。

答案 1 :(得分:0)

作为第一步,在网格中查找0。如果我们找不到,我们就完成了。

如果我们找到一个,我们知道我们应该使0的行和列中的所有1都无效。

因此,由于我们知道所有这些单元格的最终值,我们可以将该行和列用作临时布尔标志,以确定相同的行或列是否包含任何0。

确切的过程:

  • 查看矩阵以找到0。
  • 跟踪找到的坐标0。
  • 循环遍历每一行和每列,检查该行或列是否包含0,并正确设置该标志。
  • 然后再次循环遍历矩阵,对于不在标志行或列中的每个1,检查是否设置了行或列标志,如果是,则将1设置为0.
  • 然后将行和列中的所有单元格设置为标记为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(); }