[LeetCode]23. Set Matrix Zeroes矩阵清零

Given a m x n matrix, if an element is 0, set its entire row and column to 0. Do it in place.

click to show follow up.

Follow up:

Did you use extra space?
A straight forward solution using O(mn) space is probably a bad idea.
A simple improvement uses O(m + n) space, but still not the best solution.
Could you devise a constant space solution?

 
解法1:新建一个同样大小数组,先扫描行,若某行存在零元素,则整行清零;再扫描列,若某列存在零元素,则整列清零。最后将其赋给原矩阵。空间复杂度O(mn)。
class Solution {
public:
    void setZeroes(vector<vector<int>>& matrix) {
        if (matrix.empty() || matrix[0].empty())
            return;
        int m = matrix.size();
        int n = matrix[0].size();

        vector< vector<int> > tmpMat;
        for (int i = 0; i < m; i++)
        {
            tmpMat.push_back(matrix[i]);
            if (find(matrix[i].begin(), matrix[i].end(), 0) != matrix[i].end())
                tmpMat[i].assign(n, 0);
        }
        for (int j = 0; j < n; j++)
        {
            for (int i = 0; i < m; i++)
            {
                if (matrix[i][j] == 0)
                {
                    for (int k = 0; k < m; k++)
                        tmpMat[k][j] = 0;
                    break;
                }
            }
        }
        for (int i = 0; i < m; i++)
            copy(tmpMat[i].begin(), tmpMat[i].end(), matrix[i].begin());
    }
};

 

解法2:新建一个数组,用来存储矩阵中所有零元素的位置。然后再扫描一遍矩阵,将零元素所在的行列清零即可。空间复杂度O(m+n)。
class Solution {
public:
    void setZeroes(vector<vector<int>>& matrix) {
        if (matrix.empty() || matrix[0].empty())
            return;
        int m = matrix.size();
        int n = matrix[0].size();

        vector< pair<int, int> > zeroIndex;
        for (int i = 0; i < m; i++)
        {
            for (int j = 0; j < n; j++)
            {
                if (matrix[i][j] == 0)
                    zeroIndex.push_back(make_pair(i, j));
            }
        }
        for (int i = 0; i < zeroIndex.size(); i++)
        {
            for (int j = 0; j < n; j++)
                matrix[zeroIndex[i].first][j] = 0;
            for (int k = 0; k < m; k++)
                matrix[k][zeroIndex[i].second] = 0;
        }
    }
};

 

解法3:解法2中zeroIndex所用空间可以用原矩阵中某个零元素所在的行和列来代替,这样可以使得空间复杂度下降为O(1)。不需要将所有零元素的位置存下来。对于两个零元素坐标(i,j)和(k,l),如果i!=k&&k!=l,则需要将两者均存储下来,否则如果有i=k(或者j=l),则这两个零元素对矩阵行(或者列)的清零效果是一样的,只需要存储其中的一个(i或者k)(或者 j或者l)即可,而j和l(或者i和k)则必须分开存储。步骤:

- 先扫描第一行第一列,如果有0,则将各自的flag设置为true
- 然后扫描除去第一行第一列的整个数组,如果有0,则将对应的第一行和第一列的数字赋0
- 再次遍历除去第一行第一列的整个数组,如果对应的第一行和第一列的数字有一个为0,则将当前值赋0
- 最后根据第一行第一列的flag来更新第一行第一列

class Solution {
public:
    void setZeroes(vector<vector<int>>& matrix) {
        if (matrix.empty() || matrix[0].empty())
            return;
        int m = matrix.size();
        int n = matrix[0].size();

        bool rh0 = false, ch0 = false; //标识第一行和第一列是否存在0
        for (int i = 0; i < n && !rh0; i++)
            rh0 = matrix[0][i] == 0 ? true : rh0;
        for (int i = 0; i < m && !ch0; i++)
            ch0 = matrix[i][0] == 0 ? true : ch0;
        for (int i = 1; i < m; i++) //对除去原矩阵的第一行和第一列得到的新矩阵扫描,标记0的位置
        {
            for (int j = 1; j < n; j++)
            {
                if (matrix[i][j] == 0)
                {
                    matrix[i][0] = 0;
                    matrix[0][j] = 0;
                }
            }
        }
        for (int i = 1; i < m; i++) //对除去原矩阵的第一行和第一列得到的新矩阵进行清零操作
        {
            for (int j = 1; j < n; j++)
            {
                if (matrix[i][0] == 0 || matrix[0][j] == 0)
                    matrix[i][j] = 0;
            }
        }
        //对第一行第一列进行清零操作
        if (rh0)
            matrix[0].assign(n, 0);
        if (ch0)
        {
            for (int i = 0; i < m; i++)
                matrix[i][0] = 0;
        }
    }
};
posted @ 2015-10-13 19:22  AprilCheny  阅读(494)  评论(0编辑  收藏  举报