题目描述
分析
若直接在遍历数组的过程中修改,会分不清后续的0是修改后的还是原来就存在的。
所以需要用额外的空间来存储原来的数组中是否存在0,且区分各算法的优异性
两个额外数组
描述
用两个标记数组来记录每一行和每一列是否有0出现(用来更新矩阵)。接着遍历一次矩阵,根据这两个标记数组来进行更新。
代码
void setZeroes(int** matrix, int matrixSize, int* matrixColSize){
int m = matrixSize, n = matrixColSize[0];
int row[m], column[n];
int i, j;
for (i = 0; i < m;i++){
row[i] = 0;
}
for (j = 0; j < n;j++){
column[j] = 0;
}
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
if (matrix[i][j] == 0)
{
row[i] = 1;
column[j] = 1;
}
}
}
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
if (row[i]==1||column[j]==1)
{
matrix[i][j] = 0;
}
}
}
}
利用原矩阵空间进行存储
描述
利用原矩阵空间的第一行和第一列来代替额外数组进行存储。并只需要利用两个整型变量来储存原来第一行/列是否有0元素,最后再根据这两个整型变量来更新数组的第一行/列。
代码
void setZeroes(int** matrix, int matrixSize, int* matrixColSize){
int row1 = 0, column1 = 0;
int m = matrixSize, n = matrixColSize[0];
int i, j;
for (i = 0; i < m;i++){//记录第一列是否有0
if(matrix[i][0]==0){
column1 = 1;
}
}
for (j = 0; j < n;j++){//记录第一行是否有0
if(matrix[0][j]==0){
row1 = 1;
}
}
//将第一行和第一列用于储存此列/行是否有0,若有将其置为0
for (i = 1; i < m;i++){
for (j = 1; j < n;j++){
if(matrix[i][j] == 0){
matrix[0][j] = 0;
matrix[i][0] = 0;
}
}
}
for (i = 1; i < m;i++){
for (j = 1; j < n;j++){
if(matrix[0][j] == 0||matrix[i][0]==0){
matrix[i][j] = 0;
}
}
}
//处理第一行和第一列
if(row1==1){
for(j = 0; j < n;j++){
matrix[0][j] = 0;
}
}
if(column1==1){
for (i = 0; i < m;i++){
matrix[i][0] = 0;
}
}
}
第二种算法的优化
描述
注意到第二种算法没有利用到数组的[0][0]元素进行存储,因此改进后对其加以利用,
代码
void setZeroes(int** matrix, int matrixSize, int* matrixColSize){
int column1 = 0;
int m = matrixSize, n = matrixColSize[0];
int i, j;
for (i = 0; i < m;i++){//记录第一列是否有0
if(matrix[i][0]==0){
column1 = 1;
}
}
for (j = 0; j < n;j++){//记录第一行是否有0
if(matrix[0][j]==0){
matrix[0][0] = 0;//储存在[0][0]中
}
}
//将第一行和第一列用于储存此列/行是否有0,若有将其置为0
for (i = 1; i < m;i++){
for (j = 1; j < n;j++){
if(matrix[i][j] == 0){
matrix[0][j] = 0;
matrix[i][0] = 0;
}
}
}
for (i = 1; i < m;i++){
for (j = 1; j < n;j++){
if(matrix[0][j] == 0||matrix[i][0]==0){
matrix[i][j] = 0;
}
}
}
//处理第一行和第一列
if(matrix[0][0]==0){
for(j = 0; j < n;j++){
matrix[0][j] = 0;
}
}
if(column1==1){
for (i = 0; i < m;i++){
matrix[i][0] = 0;
}
}
}
收获
原地算法
对于原地算法,为了不改变原值,一般需要另外声明变量申请空间来对原值进行记忆。
当然,额外空间越少越好,因此可参照本题的做法利用原空间进行存储,并利用算法规避数据覆盖带来的麻烦。