73.矩阵置零

题目描述

73.矩阵置零_第1张图片

分析

若直接在遍历数组的过程中修改,会分不清后续的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;
        }
    }
}

收获

原地算法

对于原地算法,为了不改变原值,一般需要另外声明变量申请空间来对原值进行记忆。
当然,额外空间越少越好,因此可参照本题的做法利用原空间进行存储,并利用算法规避数据覆盖带来的麻烦。

你可能感兴趣的:(刷题笔记,矩阵,线性代数,算法)