在矩阵中,将0放在包含0的单元格的行和列中,而不使用额外的空格

时间:2014-01-13 06:28:55

标签: c++ c algorithm matrix

给定一个矩阵,如果一个单元格包含0,那么我们将整个行和列对应于该单元格为0.例如,如果

      1 2 3
M  =  0 4 5
      4 2 0

然后输出应该是

      0 2 0
      0 0 0
      0 0 0

我认为的方法如下

  1. 制作辅助数组row[]col[]。如果单元格(i,j)包含0,则将row[i]col[j]标记为0.(最初row[]col[]包含所有1)。
  2. 再次遍历整个矩阵,如果对于单元格(i,j),row[i]col[j]中的任何一个为0,则将单元格(i,j)设为0。
  3. 这需要O(m * n)时间和O(m + n)空间。

    如何在空间方面进一步优化它。欢迎任何提高时间复杂度的建议。

6 个答案:

答案 0 :(得分:10)

啊哈,这是一个老问题。

  1. 如果第一行没有元素,则使用一个布尔变量(isZeroInFirstRow)保存,如果第一列具有零个元素,则保存一个布尔变量(isZeroInFirstCol)或不。

  2. 然后,遍历整个矩阵。如果cell(i,j)==0,则将单元格(0,j)和单元格(i,0)设置为0.

  3. 遍历矩阵的第一行。如果cell(0,j)==0,则将列(j)中的所有元素设置为0。

  4. 遍历矩阵的第一列。如果cell(i,0)==0,则将行(i)中的所有元素设置为0。

  5. 如果isZeroInFirstRow==true,请将第(0)行中的所有元素设置为0.

  6. 如果isZeroInFirstCol==true,请将列(0)中的所有元素设置为0.

答案 1 :(得分:1)

您可以在O(1)空间中解决此问题。一种解决方案是迭代矩阵,对于你看到的每个0,你用一些字符填充相应的行/ col,例如'X'。

当你完成时,你应该有类似的东西:

    X 2 X
M=  0 X X
    X X 0

然后你再次迭代矩阵并用0替换每个'X'得到:

    0 2 0
M=  0 0 0
    0 0 0

答案 2 :(得分:1)

如果您关心存储,您可能会考虑使用一些稀疏矩阵storage formats来存储生成的矩阵,然后释放原始密集输入。

我提议的一个例子可能是以下(实施COO格式),这应该花费O(M * N)时间:

#include<vector>
#include<iostream>
#include<algorithm>
#include<cstddef>

using namespace std;

int main()
{
    constexpr size_t M = 3;
    constexpr size_t N = 3;
    int matrix[M][N] = {
        {1, 2, 3},
        {0, 4, 5},
        {4, 2, 0}
    };    

    vector<size_t> markedRows;
    vector<size_t> markedColumns;
    // Search for zeroes
    for (size_t ii = 0; ii < M; ++ii) {
        for(size_t jj = 0; jj < N; ++jj) {
            if (matrix[ii][jj] == 0) {
                markedRows.push_back   (ii);
                markedColumns.push_back(jj);
            }
        }
    }
    // Sort columns (rows are ordered by construction)
    sort(markedColumns.begin(),markedColumns.end());
    // Eliminate duplicates
    markedRows.erase   (unique(markedRows.begin()   ,markedRows.end())   ,markedRows.end()   );
    markedColumns.erase(unique(markedColumns.begin(),markedColumns.end()),markedColumns.end());

    // Construct COO matrix format
    vector<size_t> irow;
    vector<size_t> icol;
    vector<int>    val;        
    for (size_t ii = 0; ii < M; ++ii) {
        for(size_t jj = 0; jj < N; ++jj) {
            if ( ( find(markedRows.begin()   ,markedRows.end()   ,ii) == markedRows.end()    ) &&
                 ( find(markedColumns.begin(),markedColumns.end(),jj) == markedColumns.end() )
                ) {
                  irow.push_back(ii);
                  icol.push_back(jj);
                  val.push_back (matrix[ii][jj]);
                }
        }
    }    
    // FROM HERE YOU NO LONGER NEED MATRIX, AND YOU CAN FREE THE STORAGE

    // Print non zero entries
    for( size_t ii = 0; ii < irow.size(); ++ii) {
      cout << "A["<<irow[ii]<<","<<icol[ii]<<"] = "<<val[ii]<<endl;   
    }


    return 0;
}

答案 3 :(得分:0)

通过在matirx中搜索不包含零的行和不包含零元素的列,可以在不分配辅助行或列的情况下使用算法。

如果这些搜索中的任何一个失败,那么结果矩阵将全部为零,因此只需将所有元素设置为零即可完成工作。

否则,使用您在上面提到的簿记行和列中找到的行和列,将相应的元素设置为零,因为在矩阵的其余部分中找到零。完成该传递后,您可以走记账行,将matix列设置为零,以便在簿记行中找到任何零,类似于aux列。

答案 4 :(得分:0)

这是一个算法可以在O(M * N)时间和O(1)空间中做到: -

  
      
  1. 在矩阵中找到最大元素。
  2.   
  3. Mat [i] [j] = max - Mat [i] [j] for all(i,j)
  4.   
  5. 请注意,Mat [i] [j]只会有正值。
  6.   
  7. 使用negetive值作为标记,Mat [i] [j] = max为零。
  8.   
  9. 以Mat [i] [j] = max - Mat [i] [j]
  10. 的形式检索原始值   

答案 5 :(得分:0)

简单易行的答案:  &lt; 2嵌套循环&gt;要搜索所有列和行,您会在所有列中找到任何cell = 0,并将其设置为所有行的零并将其设置为零。如果不清楚为它录制视频,请告诉我。

Int main()
{
//example matrix dimension rows(r=6) * columns (c=3)
int r = 6;
int c = 3;
int matrix[r][c];

for(int i=0; i<r; ++i){
    for(int j=0 ; j < c ; ++j){
        if(matrix[i][j] == 0){ 
            for(int ii=0; ii<r; ++ii){
                Matrix[ii][j] = 0 ;
            }
            for(int jj=0; jj<c; ++jj){
                Matrix[i][jj] = 0 ;
            }
       }
   }  
}
}
相关问题