给定一个矩阵,如果一个单元格包含0,那么我们将整个行和列对应于该单元格为0.例如,如果
1 2 3
M = 0 4 5
4 2 0
然后输出应该是
0 2 0
0 0 0
0 0 0
我认为的方法如下
row[]
和col[]
。如果单元格(i,j)包含0,则将row[i]
和col[j]
标记为0.(最初row[]
和col[]
包含所有1)。row[i]
或col[j]
中的任何一个为0,则将单元格(i,j)设为0。这需要O(m * n)时间和O(m + n)空间。
如何在空间方面进一步优化它。欢迎任何提高时间复杂度的建议。
答案 0 :(得分:10)
啊哈,这是一个老问题。
如果第一行没有元素,则使用一个布尔变量(isZeroInFirstRow
)保存,如果第一列具有零个元素,则保存一个布尔变量(isZeroInFirstCol
)或不。
然后,遍历整个矩阵。如果cell(i,j)==0
,则将单元格(0,j)和单元格(i,0)设置为0.
遍历矩阵的第一行。如果cell(0,j)==0
,则将列(j)中的所有元素设置为0。
遍历矩阵的第一列。如果cell(i,0)==0
,则将行(i)中的所有元素设置为0。
如果isZeroInFirstRow==true
,请将第(0)行中的所有元素设置为0.
如果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)空间中做到: -
- 在矩阵中找到最大元素。
- Mat [i] [j] = max - Mat [i] [j] for all(i,j)
- 请注意,Mat [i] [j]只会有正值。
- 使用negetive值作为标记,Mat [i] [j] = max为零。
- 以Mat [i] [j] = max - Mat [i] [j]
的形式检索原始值 醇>
答案 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 ;
}
}
}
}
}