(每日算法)LeetCode--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.

最直观的解法就是开辟一个新的矩阵,当原矩阵存在零元素的时候,就将新矩阵的对应行和列置为零。这样空间复杂度较高,也是题目不允许的。

题目的难点就在于,如果遇到零元素之后马上在矩阵上操作,将所在的行和列都置为零。在接下来的遍历中,如果你再遇到零,你讲不清楚是原矩阵的零还是你修改之后的零。所以,一种方法就是先通过两个数组来记录该行该列上有没有零元素,等对矩阵遍历完之后再统一修改即可

class Solution {
public:
    void setZeroes(vector<vector<int> > &matrix) {

	    const size_t m = matrix.size();
	    const size_t n = matrix[0].size();
	    vector<bool> row(m, false); //标记该行是否存在0
	    vector<bool> col(n, false);

	    for(int i = 0; i < matrix.size(); i++)
	    {
	    	for(int j = 0; j < matrix[0].size(); j++)
		{
			if(matrix[i][j] == 0)
				row[i] = col[j] = true;//如果原矩阵中存在0,记录该行和列的位置。
		}
	    }

	 for (size_t i = 0; i < m; ++i) {
		if (row[i])
			fill(&matrix[i][0], &matrix[i][0] + n, 0);//将矩阵的一行置为零
		}
	for (size_t j = 0; j < n; ++j) {
		if (col[j]) {
			for (size_t i = 0; i < m; ++i)
				matrix[i][j] = 0;//将矩阵的一列置为0
		       	}
	}
    }
};

fill函数的作用是:将一个区间的元素都赋予val值。函数参数:fill(first,last,val);//first为容器的首迭代器,last为容器的末迭代器,val为将要替换的值。

作用和下面的函数相同:

template <class ForwardIterator, class T>
  void fill (ForwardIterator first, ForwardIterator last, const T& val)
{
  while (first != last) {
    *first = val;
    ++first;
  }
}

使用fill函数的一个例子:

// fill algorithm example
#include <iostream>     // std::cout
#include <algorithm>    // std::fill
#include <vector>       // std::vector

int main () {
  std::vector<int> myvector (8);                       // myvector: 0 0 0 0 0 0 0 0

  std::fill (myvector.begin(),myvector.begin()+4,5);   // myvector: 5 5 5 5 0 0 0 0
  std::fill (myvector.begin()+3,myvector.end()-2,8);   // myvector: 5 5 5 8 8 8 0 0

  std::cout << "myvector contains:";
  for (std::vector<int>::iterator it=myvector.begin(); it!=myvector.end(); ++it)
    std::cout << ' ' << *it;
  std::cout << '\n';

  return 0;
}

输出是:myvector contains: 5 5 5 8 8 8 0 0

fill_n函数的作用是:给你一个起始点,然后再给你一个数值count和val。把从起始点开始依次赋予count个元素val的值

相当于下面的函数:

template <class OutputIterator, class Size, class T>
  OutputIterator fill_n (OutputIterator first, Size n, const T& val)
{
  while (n>0) {
    *first = val;
    ++first; --n;
  }
  return first;     // since C++11
}

在C++11中返回首迭代器的值,在c++98中什么都不返回。n在98中不能为负数,在11中,如果为负数,则什么也不做。

一个例子:

// fill_n example
#include <iostream>     // std::cout
#include <algorithm>    // std::fill_n
#include <vector>       // std::vector

int main () {
  std::vector<int> myvector (8,10);        // myvector: 10 10 10 10 10 10 10 10

  std::fill_n (myvector.begin(),4,20);     // myvector: 20 20 20 20 10 10 10 10
  std::fill_n (myvector.begin()+3,3,33);   // myvector: 20 20 20 33 33 33 10 10

  std::cout << "myvector contains:";
  for (std::vector<int>::iterator it=myvector.begin(); it!=myvector.end(); ++it)
    std::cout << ' ' << *it;
  std::cout << '\n';

  return 0;
}

这也就引出来指针和迭代器的区别:

相同点---指针和iterator都支持与整数进行+,-运算,而且其含义都是从当前位置向前或者向后移动n个位置;指针和iterator都支持减法运算,指针-指针得到的是两个指针之间的距离,迭代器-迭代器得到的是两个迭代器之间的距离; 通过指针或者iterator都能够修改其指向的元素。

不同点--- cout操作符可以直接输出指针的值,但是对迭代器进行在操作的时候会报错。通过看报错信息和头文件知道,迭代器返回的是对象引用而不是对象的值,所以cout只能输出迭代器使用*取值后的值而不能直接输出其自身;  指针能指向函数而迭代器不行,迭代器只能指向容器。

指针是一种特殊的变量,它专门用来存放另一变量的地址,而迭代器只是参考了指针的特性进行设计的一种STL接口。

网上有这样一种说法:迭代器是广义指针,而指针满足所有迭代器要求。迭代器是STL算法的接口,而指针是迭代器,因此STL算法可以使用指针来对基于指针的非STL容器进行操作。

也许某些编译器使用指针来实现迭代器以至于有些人会误以为指针和迭代器是一个概念来的。

迭代器并不是普通的指针,可以说是智能指针。只有在vector容器中Iterator才是普通的指针。其他情况Iterator都是比较复杂的数据就够。Iterator分为了只读、只写、向前、双向和随机访问五种不同的类型。根据容器的不同和使用的情况,Iterator使用不同的类型。像List就是双向的Iterator。所有的Iterator都符合左闭右开的原则。

时间: 2025-01-02 18:22:57

(每日算法)LeetCode--Set Matrix Zeroes (矩阵置零)的相关文章

[Leetcode] 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(m n) space is probably a bad idea.A simple improvement uses

[LeetCode] 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

[CareerCup] 1.7 Set Matrix Zeroes 矩阵赋零

1.7 Write an algorithm such that if an element in an MxN matrix is 0, its entire row and column are set to 0. LeetCode中的原题,请参见我之前的博客Set Matrix Zeroes 矩阵赋零.

LeetCode—Set Matrix Zeroes 矩阵数组值为0,至行,列为0

Given a m x n matrix, if an element is 0, set its entire row and column to 0. Do it in place. 题目没有什么难度,但是可以在空间复杂度上做一些处理: 开始写的算法比较简单,将行和列中为0的部分记录下来,然后再经过一个赋值操作: class Solution { public: void setZeroes(vector<vector<int> > &matrix) { if(matr

73. 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

【LeetCode-面试算法经典-Java实现】【070-Set Matrix Zeroes(矩阵置零)】

[070-Set Matrix Zeroes(矩阵置零)] [LeetCode-面试算法经典-Java实现][所有题目目录索引] 原题 Given a m x n matrix, if an element is 0, set its entire row and column to 0. Do it in place. 题目大意 给定一个m*n的矩阵,如果某个位置是0.将对应的行和列设置为0. 解题思路 先对矩阵进行扫描,标记要进行置0的行和列,对要进行置0的行在第0列上进行标记,对置0的列在

LeetCode: Set Matrix Zeroes [073]

[题目] Given a m x n matrix, if an element is 0, set its entire row and column to 0. Do it in place. [题意] 给定一个mXn的矩阵,如果其中的元素为0,则对应的行和列都用0填充. 不能申请额外的空间. [思路] 第一行和第一列空出来标记需要置0的列和行 第一遍扫描: 扫描第一行,判断第一行是否需要清零 扫描第一列,判断第一列是否需要清零 扫描[1,1]~[m-1, n-1]的区块,如果某个位置上的值

代码题(38)— 旋转图像、矩阵置零

1.48. 旋转图像 给定一个 n × n 的二维矩阵表示一个图像. 将图像顺时针旋转 90 度. 说明: 你必须在原地旋转图像,这意味着你需要直接修改输入的二维矩阵.请不要使用另一个矩阵来旋转图像. 示例 1: 给定 matrix = [ [1,2,3], [4,5,6], [7,8,9] ], 原地旋转输入矩阵,使其变为: [ [7,4,1], [8,5,2], [9,6,3] ] 示例 2: 给定 matrix = [ [ 5, 1, 9,11], [ 2, 4, 8,10], [13,

Set Matrix Zeroes 将矩阵置零

给定一个矩阵,把零值所在的行和列都置为零.例如: 1 2 3 1 0 3 1 1 1 操作之后变为 1 0 3 0 0 0 1 0 1 方法1: 赋值另存一个m*n的矩阵,在原矩阵为零的值相应置新的矩阵行和列为零.额外空间为O(m*n). 方法2: 两个数组,bool[m] 和 bool[n] 分别存某行有零,后者某列有零.之后根据数组值将原矩阵相应位置置零.额外空间O(m + n). class Solution { public: void setZeroes(vector<vector<