LeetCodeDay36 —— 矩阵置零★★☆

73. 矩阵置零

描述
  • 给定一个 m x n 的矩阵,如果一个元素为 0,则将其所在行和列的所有元素都设为 0。请使用原地算法。
示例
示例 1:
  输入:
    [
      [1,1,1],
      [1,0,1],
      [1,1,1]
    ]
  输出:
    [
      [1,0,1],
      [0,0,0],
      [1,0,1]
    ]
示例 2:
  输入:
    [
      [0,1,2,0],
      [3,4,5,2],
      [1,3,1,5]
    ]
  输出:
    [
      [0,0,0,0],
      [0,4,5,0],
      [0,3,1,0]
    ]
进阶:
  一个直接的解决方案是使用  O(mn) 的额外空间,但这并不是一个好的解决方案。
  一个简单的改进方案是使用 O(m + n) 的额外空间,但这仍然不是最好的解决方案。
  你能想出一个常数空间的解决方案吗?
思路
  1. 时间复杂度O(mn),空间复杂度O(mn)的算法,复制一份Matrix,将0对应行列的元素置位0.
  2. 时间复杂度O(mn),空间复杂度O(m + n)的算法,利用一个M大小和一个N大小的数组,保存0元素的小标,然后将对应行列的元素置位0.
  3. 时间复杂度O(mn),空间复杂度O(1)的算法,利用首行首列的元素来表示该行该列是否有0元素,然后将对应行列的元素置位0.该方法需先统计首行首列自己是否有0元素,最后将首行首列置0.(参考)
Tips
  1. 题目需要遍历每个元素,所以时间复杂度O(mn)是较难优化的,突破点在于空间复杂度。
  2. 第一种解法直接复制了整个数组,仔细思考下其实只需保存0元素的小标即可,此时可将空间复杂度优化为O(m + n)
  3. 进一步优化,要将空间复杂度降为O(1),则需利用数组本身来保存0的位置了。不难想到可以将上述额外的两个数组转换为首行首列,具体步骤如下:
    1)检查并记录第一行和第一列是否需要归零;
    2)遍历矩阵,一旦发现某个元素为0,则将它所在的行和列的第一个元素置为0;
    3)遍历第一行和第一列,如果是0,则将其对应的整个行或者整个列的元素置为0;
    4)如果第一行或者第一列需要归零,则将其归零。时间复杂度为O(m*n),空间复杂度为O(1)。
class Solution_73_01 {
 public:
  void setZeroes(vector<vector<int>>& matrix) {
    vector<vector<int>> tmp = matrix;
    for (int i = 0; i < matrix.size(); ++i) {
      for (int j = 0; j < matrix[i].size(); ++j) {
        if (tmp[i][j] == 0) {
          for (int k = 0; k != matrix[i].size(); ++k) matrix[i][k] = 0;
          for (int k = 0; k != matrix.size(); ++k) matrix[k][j] = 0;
        }
      }
    }
  }
};

class Solution_73_02 {
 public:
  void setZeroes(vector<vector<int>>& matrix) {
    if (matrix.empty()) return;
    int hight = matrix.size(), width = matrix[0].size();
    vector<bool> row0, col0;
    row0.assign(hight, false);
    col0.assign(width, false);
    for (int i = 0; i < hight; ++i) {  //记录0点的位置
      for (int j = 0; j < width; ++j) {
        if (matrix[i][j] == 0) {
          row0[i] = true;
          col0[j] = true;
        }
      }
    }
    for (int i = 0; i < row0.size(); ++i) {
      if (!row0[i]) continue;
      for (int j = 0; j < width; ++j) {
        matrix[i][j] = 0;
      }
    }
    for (int i = 0; i < col0.size(); ++i) {
      if (!col0[i]) continue;
      for (int j = 0; j < hight; ++j) {
        matrix[j][i] = 0;
      }
    }
  }
};

class Solution_73_03 {
 public:
  void setZeroes(vector<vector<int>>& matrix) {
    if (matrix.empty()) return;
    int hight = matrix.size(), width = matrix[0].size();
    bool isHasZeroRow = false, isHasZeroCol = false;
    for (int i = 0; i < hight; ++i) {
      if (matrix[i][0] == 0) {
        isHasZeroRow = true;
        break;
      }
    }
    for (int i = 0; i < width; ++i) {
      if (matrix[0][i] == 0) {
        isHasZeroCol = true;
        break;
      }
    }
    // 将0元素所在行列的第一个元素置为0
    for(int i = 1; i < hight; ++i){
      for(int j = 1; j < width; ++j){
        if(matrix[i][j] == 0){
          matrix[i][0] = 0;
          matrix[0][j] = 0;
        }
      }
    }

    // 根据首行、首列将对应元素置0
    for(int row = 1; row < hight; ++row){
      if(matrix[row][0] == 0){
        for(int col = 1; col < width; ++col){
          matrix[row][col] = 0;
        }
      }
    }
    for(int col = 1; col < width; ++col){
      if(matrix[0][col] == 0){
        for(int row = 1; row < hight; ++row){
          matrix[row][col] = 0;
        }
      }
    }

    cout<< isHasZeroRow << " " << isHasZeroCol << endl;
    // 处理首行、首列
    if(isHasZeroRow){
      for(int i = 0; i < hight; ++i){
        matrix[i][0] = 0;
      }
    }
    if(isHasZeroCol){
      for(int i = 0; i < width; ++i){
        matrix[0][i] = 0;
      }
    }
  }
};
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 给定一个 m x n 的矩阵,如果一个元素为 0,则将其所在行和列的所有元素都设为 0。请使用原地算法。 进阶: ...
    susu2016阅读 2,271评论 0 2
  • 9.3.3 快速排序   快速排序将原数组划分为两个子数组,第一个子数组中元素小于等于某个边界值,第二个子数组中的...
    RichardJieChen阅读 1,873评论 0 3
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,001评论 19 139
  • 10月13日,晚,微信聊天,对面,是自己的好朋友,只是,聊到最后,却未如以往开开心心结束,看着床边的书,没有...
    依恋三国情阅读 291评论 0 1
  • 分割线满屏 隐藏某一个cell分割线 [cell setSeparatorInset:UIEdgeInsetsMa...
    vision_colion阅读 412评论 0 3